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-2025 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.reset();
50  }
51 }; //end struct fe_iface::priv
52 
53 /// Constructor of the type @ref fe_iface::options_type.
54 ///
55 /// @param e the environment used by the Front End Interface.
57  : env(e)
58 {
59 }
60 
61 /// Constructor of the type @ref fe_iface.
62 ///
63 /// @param corpus_path the path to the file represented by the ABI
64 /// corpus that is going to be built by this Front End.
65 ///
66 /// @param e the environment in which the Front End operates.
67 fe_iface::fe_iface(const std::string& corpus_path, environment& e)
68  : priv_(new priv(corpus_path, e))
69 {
70 }
71 
72 /// Desctructor of the Front End Interface.
74 {delete priv_;}
75 
76 /// Re-initialize the current Front End.
77 ///
78 /// @param corpus_path the path to the file for which a new corpus is
79 /// to be created.
80 void
81 fe_iface::initialize(const std::string& corpus_path)
82 {
83  priv_->initialize();
84  priv_->corpus_path = corpus_path;
85 }
86 
87 /// Getter of the the options of the current Front End Interface.
88 ///
89 /// @return the options of the current Front End Interface.
92 {return priv_->options;}
93 
94 /// Getter of the the options of the current Front End Interface.
95 ///
96 /// @return the options of the current Front End Interface.
99 {return priv_->options;}
100 
101 /// Getter of the path to the file which an ABI corpus is to be
102 /// created for.
103 ///
104 /// @return the path to the file which an ABI corpus is to be created
105 /// for.
106 const std::string&
108 {return priv_->corpus_path;}
109 
110 /// Setter of the path to the file which an ABI corpus is to be
111 /// created for.
112 ///
113 /// @param p the new path to the file which an ABI corpus is to be
114 /// created for.
115 void
116 fe_iface::corpus_path(const std::string& p)
117 {priv_->corpus_path = p;}
118 
119 /// Getter for the SONAME of the analyzed binary.
120 ///
121 /// @return the SONAME of the analyzed binary.
122 const string&
124 {return priv_->dt_soname;}
125 
126 /// Getter for the SONAME of the analyzed binary.
127 ///
128 /// @return the SONAME of the analyzed binary.
129 void
130 fe_iface::dt_soname(const string& soname)
131 {priv_->dt_soname = soname;}
132 
133 /// Test if the input binary is to be considered as a Linux Kernel
134 /// binary.
135 ///
136 /// @return true iff the input binary is to be considered as a Linux
137 /// Kernel binary.
138 bool
140 {return priv_->options.load_in_linux_kernel_mode;}
141 
142 /// Getter of the vector of suppression specifications associated with
143 /// the current front-end.
144 ///
145 /// @return the vector of suppression specifications associated with
146 /// the current front-end.
149 {return priv_->suppressions;}
150 
151 /// Getter of the vector of suppression specifications associated with
152 /// the current front-end.
153 ///
154 /// @return the vector of suppression specifications associated with
155 /// the current front-end.
158 {return priv_->suppressions;}
159 
160 /// Setter of the vector of suppression specifications associated with
161 /// the current front-end.
162 ///
163 /// @param supprs the new vector of suppression specifications
164 /// associated with the current front-end.
165 void
167 {priv_->suppressions = supprs;}
168 
169 /// Add suppressions specifications to the set of suppressions to be
170 /// used during the construction of the ABI internal representation
171 /// (the ABI corpus) from the input file.
172 ///
173 /// During the construction of the ABI corpus, ABI artifacts that
174 /// match a given suppression specification are dropped on the floor;
175 /// that is, they are discarded and won't be part of the final ABI
176 /// corpus. This is a way to reduce the amount of data held by the
177 /// final ABI corpus.
178 ///
179 /// Note that the suppression specifications provided to this function
180 /// are only considered during the construction of the ABI corpus.
181 /// For instance, they are not taken into account during e.g
182 /// comparisons of two ABI corpora that might happen later. If you
183 /// want to apply suppression specificatins to the comparison (or
184 /// reporting) of ABI corpora please refer to the documentation of the
185 /// @ref diff_context type to learn how to set suppressions that are
186 /// to be used in that context.
187 ///
188 /// @param supprs the suppression specifications to be applied during
189 /// the construction of the ABI corpus.
190 void
192 {
193  for (const auto& s : supprs)
194  if (s->get_drops_artifact_from_ir())
195  suppressions().push_back(s);
196 }
197 
198 /// Getter for the ABI corpus being built by the current front-end.
199 ///
200 /// @return the ABI corpus being built by the current front-end.
201 corpus_sptr
203 {
204  if (!priv_->corpus)
205  {
206  priv_->corpus = std::make_shared<ir::corpus>(options().env,
207  corpus_path());
208  }
209  return priv_->corpus;
210 }
211 
212 /// Getter for the ABI corpus being built by the current front-end.
213 ///
214 /// @return the ABI corpus being built by the current front-end.
215 const corpus_sptr
217 {return const_cast<fe_iface*>(this)->corpus();}
218 
219 /// Getter for the ABI corpus group being built by the current front-end.
220 ///
221 /// @return the ABI corpus group being built by the current front-end.
222 corpus_group_sptr&
224 {return priv_->corpus_group;}
225 
226 /// Getter for the ABI corpus group being built by the current front-end.
227 ///
228 /// @return the ABI corpus group being built by the current front-end.
229 const corpus_group_sptr&
231 {return const_cast<fe_iface*>(this)->corpus_group();}
232 
233 /// Setter for the ABI corpus group being built by the current
234 /// front-end.
235 ///
236 /// @param cg the new ABI corpus group being built by the current
237 /// front-end.
238 void
239 fe_iface::corpus_group(const ir::corpus_group_sptr& cg)
240 {priv_->corpus_group = cg;}
241 
242 /// Test if there is a corpus group being built.
243 ///
244 /// @return if there is a corpus group being built, false otherwise.
245 bool
247 {return bool(corpus_group());}
248 
249 /// Return the main corpus from the current corpus group, if any.
250 ///
251 /// @return the main corpus of the current corpus group, if any, nil
252 /// if no corpus group is being constructed.
253 corpus_sptr
255 {
256  if (corpus_group())
257  return corpus_group()->get_main_corpus();
258  return corpus_sptr();
259 }
260 
261 /// Test if the current corpus being built is the main corpus of the
262 /// current corpus group.
263 ///
264 /// @return return true iff the current corpus being built is the
265 /// main corpus of the current corpus group.
266 bool
268 {
269  corpus_sptr main_corpus = main_corpus_from_current_group();
270 
271  if (main_corpus.get() == corpus().get())
272  return true;
273 
274  return false;
275 }
276 
277 /// Return true if the current corpus is part of a corpus group
278 /// being built and if it's not the main corpus of the group.
279 ///
280 /// For instance, this would return true if we are loading a linux
281 /// kernel *module* that is part of the current corpus group that is
282 /// being built. In this case, it means we should re-use types
283 /// coming from the "vmlinux" binary that is the main corpus of the
284 /// group.
285 ///
286 /// @return the corpus group the current corpus belongs to, if the
287 /// current corpus is part of a corpus group being built. Nil otherwise.
288 corpus_sptr
290 {
291  if (has_corpus_group())
292  if (corpus_sptr main_corpus = main_corpus_from_current_group())
294  return corpus_group();
295 
296  return corpus_sptr();
297 }
298 
299 /// Add the representation of the ABI of a function to the set of
300 /// exported declarations or undefined declarations of the current
301 /// corpus.
302 ///
303 /// Note that if the function is defined and exported, then it's going
304 /// to be added to the set of functions exported by the current
305 /// corpus. Otherwise, if the function has an undefined symbol then
306 /// it's going to be added to the sef of undefined functions used by
307 /// the current corpus.
308 ///
309 /// @param fn the internal representation of the ABI of a function.
310 void
312 {
313  bool added = false;
314  if (fn)
316  corpus()->get_exported_decls_builder().get())
317  added = b->maybe_add_fn_to_exported_fns(const_cast<function_decl*>(fn));
318 
319  if (fn && !added)
320  {
321  if (!fn->get_symbol() || !fn->get_symbol()->is_defined())
322  corpus()->get_undefined_functions().insert(fn);
323  }
324 }
325 
326 /// Add the representation of the ABI of a variable to the set of
327 /// exported or undefined declarations of the current corpus.
328 ///
329 /// Note that if the variable is defined and exported, then it's going
330 /// to be added to the set of variables exported by the current
331 /// corpus. Otherwise, if the variable has an undefined symbol then
332 /// it's going to be added to the sef of undefined variables used by
333 /// the current corpus.
334 ///
335 /// @param var the internal representation of the ABI of a variable.
336 void
338 {
339  bool added = false;
340  if (var)
342  corpus()->get_exported_decls_builder().get())
343  added = b->maybe_add_var_to_exported_vars(var);
344 
345  if (var && !added)
346  {
347  if (!var->get_symbol() || !var->get_symbol()->is_defined())
348  corpus()->get_undefined_variables().insert(var);
349  }
350 }
351 
352 /// The bitwise OR operator for the @ref fe_iface::status type.
353 ///
354 /// @param l the left-hand side operand.
355 ///
356 /// @param r the right-hand side operand.
357 ///
358 /// @return the result of the operation.
361 {
362  return static_cast<fe_iface::status>(static_cast<unsigned>(l)
363  | static_cast<unsigned>(r));
364 }
365 
366 /// The bitwise AND operator for the @ref fe_iface::status type.
367 ///
368 /// @param l the left-hand side operand.
369 ///
370 /// @param r the right-hand side operand.
371 ///
372 /// @return the result of the operation.
375 {
376  return static_cast<fe_iface::status>(static_cast<unsigned>(l)
377  & static_cast<unsigned>(r));
378 }
379 
380 /// The bitwise |= operator for the @ref fe_iface::status type.
381 ///
382 /// @param l the left-hand side operand.
383 ///
384 /// @param r the right-hand side operand.
385 ///
386 /// @return the result of the operation.
389 {
390  l = l | r;
391  return l;
392 }
393 
394 /// The bitwise &= operator for the @ref fe_iface::status type.
395 ///
396 /// @param l the left-hand side operand.
397 ///
398 /// @param r the right-hand side operand.
399 ///
400 /// @return the result of the operation.
403 {
404  l = l & r;
405  return l;
406 }
407 
408 /// Return a diagnostic status with english sentences to describe the
409 /// problems encoded in a given abigail::elf_reader::status, if
410 /// there is an error.
411 ///
412 /// @param status the status to diagnose
413 ///
414 /// @return a string containing sentences that describe the possible
415 /// errors encoded in @p s. If there is no error to encode, then the
416 /// empty string is returned.
417 std::string
419 {
420  std::string str;
421 
423  str += "could not find debug info";
424 
426  str += "could not find alternate debug info";
427 
429  str += "could not load ELF symbols";
430 
431  return str;
432 }
433 
434 }// 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:91
options_type(environment &)
Constructor of the type fe_iface::options_type.
Definition: abg-fe-iface.cc:56
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:23027
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
shared_ptr< var_decl > var_decl_sptr
Convenience typedef for a shared pointer on a var_decl.
Definition: abg-fwd.h:253
fe_iface::status & operator&=(fe_iface::status &l, fe_iface::status r)
The bitwise &= operator for the fe_iface::status type.
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.
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:3164
void add_var_to_exported_or_undefined_decls(const var_decl_sptr &var)
Add the representation of the ABI of a variable to the set of exported or undefined declarations of t...
This is an abstraction of the set of resources necessary to manage several aspects of the internal re...
Definition: abg-ir.h:147
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:67
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:1687
Abstracts the building of the set of exported variables and functions.
Definition: abg-corpus.h:336
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:73
virtual void initialize(const std::string &corpus_path)
Re-initialize the current Front End.
Definition: abg-fe-iface.cc:81
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