mirror of
https://github.com/openharmony/third_party_libabigail.git
synced 2026-07-18 16:54:37 -04:00
Handle the life time of the map of canonical types
While working on something else, it turned out that we need to cleanup (de-allocate) the map of canonical types when all the translation units that own types are de-allocated. Otherwise, when new translation units are created later, the types in the canonical types map become unrelated to the types in these new translation units, leading to memory management issues. This patch introduces a "usage watchdog" which detects when no translation unit uses the type system anymore. That usage watchdog is then used in the destructor of the translation_unit type to de-allocate the global data that is logically owned by by the type system. The patch also changes the API to read translation units and corpora in a way that forces users to get a handle on the resulting shared pointer. * include/abg-ir.h (type_base::canonical_types_map_type): Move this typedef into abg-ir.cc and out of the type_base namespace. (type_base::get_canonical_types_map): Likewise. * src/abg-ir.cc (canonical_types_map_type): New typedef that got moved here from type_base::canonical_types_map_type. (get_canonical_types_map): Likewise got moved here from type_base::get_canonical_types_map. Made static in the process. (class usage_watchdog): New type. (usage_watchdog_sptr, usage_watchdog_wptr): New typedefs. (get_usage_watchdog, get_usage_watchdog_wptr, ref_usage_watchdog) (maybe_cleanup_type_system_data): New static functions. (translation_unit::priv::usage_watchdog_): Add new data member. (translation_unit::priv::priv): Get a reference on the usage watchdog. (translation_unit::priv::~priv): If the usage watchdog says that the type system is not used, then cleanup the global data logically owned by the type system. * include/abg-dwarf-reader.h (read_corpus_from_elf): Make this return a corpus and set the status by reference using a parameter. * src/abg-dwarf-reader.cc (read_corpus_from_elf): Implement the above. * include/abg-reader.h (read_translation_unit_from_file) (read_translation_unit_from_buffer) (read_translation_unit_from_istream): Remove the overloads that do not return a translation_unit_sptr and that pass it as a parameter. Only keep the overloads that return a translation_unit_sptr, forcing users of the API to own a proper reference on the resulting translation_unit pointer. That is important to handle the life time of the global data of the type system that need to be cleared when the last translation unit is de-allocated. * src/abg-reader.cc (read_translation_unit_from_input): Make this return a translation_unit_sptr. (read_translation_unit_from_file) (read_translation_unit_from_buffer) (read_translation_unit_from_istream): Remove the overloads that do not return a translation_unit_sptr and that pass it as a parameter. Only keep the overloads that return a translation_unit_sptr. (read_to_translation_unit): Make this return a translation_unit_sptr. * tests/print-diff-tree.cc (main): Adjust. * tests/test-diff-dwarf.cc (main): Likewise. * tests/test-ir-walker.cc (main): Likewise. * tests/test-read-dwarf.cc (main): Likewise. * tests/test-read-write.cc (main): Likewise. * tools/abicompat.cc (main): Likewise. * tools/abidiff.cc (main): Likewise. * tools/abidw.cc (main): Likewise. * tools/abilint.cc (main): Likewise. Signed-off-by: Dodji Seketeli <dodji@redhat.com>
This commit is contained in:
@@ -80,14 +80,16 @@ create_read_context(const std::string& elf_path,
|
||||
char** debug_info_root_path,
|
||||
bool read_all_types = false);
|
||||
|
||||
status
|
||||
|
||||
corpus_sptr
|
||||
read_corpus_from_elf(read_context& ctxt,
|
||||
corpus_sptr& resulting_corp);
|
||||
status
|
||||
status&);
|
||||
|
||||
corpus_sptr
|
||||
read_corpus_from_elf(const std::string& elf_path,
|
||||
char** debug_info_root_path,
|
||||
bool load_all_types,
|
||||
corpus_sptr& resulting_corp);
|
||||
status&);
|
||||
|
||||
bool
|
||||
lookup_symbol_from_elf(const string& elf_path,
|
||||
|
||||
@@ -1012,14 +1012,6 @@ class type_base : public virtual type_or_decl_base
|
||||
// Forbid this.
|
||||
type_base();
|
||||
|
||||
/// A convenience typedef for a map of canonical types. The a map
|
||||
/// entry key is the hash value of a particular type and the value
|
||||
/// is the list of canonical types that have the same hash value.
|
||||
typedef std::tr1::unordered_map<size_t,
|
||||
std::list<type_base_sptr> > canonical_types_map_type;
|
||||
|
||||
static canonical_types_map_type&
|
||||
get_canonical_types_map();
|
||||
|
||||
static type_base_sptr
|
||||
get_canonical_type_for(type_base_sptr);
|
||||
|
||||
@@ -43,24 +43,9 @@ using namespace abigail::ir;
|
||||
translation_unit_sptr
|
||||
read_translation_unit_from_file(const std::string& file_path);
|
||||
|
||||
bool
|
||||
read_translation_unit_from_file(const string& input_file,
|
||||
translation_unit& tu);
|
||||
|
||||
bool
|
||||
read_translation_unit_from_file(translation_unit& tu);
|
||||
|
||||
translation_unit_sptr
|
||||
read_translation_unit_from_buffer(const std::string& file_path);
|
||||
|
||||
bool
|
||||
read_translation_unit_from_buffer(const string& buffer,
|
||||
translation_unit& tu);
|
||||
|
||||
bool
|
||||
read_translation_unit_from_istream(std::istream* in,
|
||||
translation_unit& tu);
|
||||
|
||||
translation_unit_sptr
|
||||
read_translation_unit_from_istream(std::istream* in);
|
||||
|
||||
|
||||
+9
-10
@@ -7914,10 +7914,10 @@ create_read_context(const std::string& elf_path,
|
||||
/// @param resulting_corp a pointer to the resulting abigail::corpus.
|
||||
///
|
||||
/// @return the resulting status.
|
||||
status
|
||||
read_corpus_from_elf(read_context& ctxt, corpus_sptr& resulting_corp)
|
||||
corpus_sptr
|
||||
read_corpus_from_elf(read_context& ctxt, status& status)
|
||||
{
|
||||
enum status status = STATUS_UNKNOWN;
|
||||
status = STATUS_UNKNOWN;
|
||||
|
||||
// Load debug info from the elf path.
|
||||
if (!ctxt.load_debug_info())
|
||||
@@ -7930,7 +7930,7 @@ read_corpus_from_elf(read_context& ctxt, corpus_sptr& resulting_corp)
|
||||
ctxt.load_remaining_elf_data();
|
||||
|
||||
if (status & STATUS_NO_SYMBOLS_FOUND)
|
||||
return status;
|
||||
return corpus_sptr();
|
||||
|
||||
// Read the variable and function descriptions from the debug info
|
||||
// we have, through the dwfl handle.
|
||||
@@ -7946,10 +7946,9 @@ read_corpus_from_elf(read_context& ctxt, corpus_sptr& resulting_corp)
|
||||
corp->set_var_symbol_map(ctxt.var_syms_sptr());
|
||||
corp->set_undefined_var_symbol_map(ctxt.undefined_var_syms_sptr());
|
||||
|
||||
resulting_corp = corp;
|
||||
|
||||
status |= STATUS_OK;
|
||||
return status;
|
||||
|
||||
return corp;
|
||||
}
|
||||
|
||||
/// Read all @ref abigail::translation_unit possible from the debug info
|
||||
@@ -7975,11 +7974,11 @@ read_corpus_from_elf(read_context& ctxt, corpus_sptr& resulting_corp)
|
||||
/// @param resulting_corp a pointer to the resulting abigail::corpus.
|
||||
///
|
||||
/// @return the resulting status.
|
||||
status
|
||||
corpus_sptr
|
||||
read_corpus_from_elf(const std::string& elf_path,
|
||||
char** debug_info_root_path,
|
||||
bool load_all_types,
|
||||
corpus_sptr& resulting_corp)
|
||||
status& status)
|
||||
{
|
||||
// Create a DWARF Front End Library handle to be used by functions
|
||||
// of that library.
|
||||
@@ -7989,7 +7988,7 @@ read_corpus_from_elf(const std::string& elf_path,
|
||||
c->load_all_types(load_all_types);
|
||||
read_context& ctxt = *c;
|
||||
|
||||
return read_corpus_from_elf(ctxt, resulting_corp);
|
||||
return read_corpus_from_elf(ctxt, status);
|
||||
}
|
||||
|
||||
/// Look into the symbol tables of a given elf file and see if we find
|
||||
|
||||
+117
-3
@@ -50,6 +50,96 @@ using std::tr1::unordered_map;
|
||||
using std::tr1::dynamic_pointer_cast;
|
||||
using std::tr1::static_pointer_cast;
|
||||
|
||||
// A convenience typedef for a map of canonical types. The a map
|
||||
/// entry key is the hash value of a particular type and the value
|
||||
/// is the list of canonical types that have the same hash value.
|
||||
typedef std::tr1::unordered_map<size_t,
|
||||
std::list<type_base_sptr> > canonical_types_map_type;
|
||||
|
||||
static canonical_types_map_type& get_canonical_types_map();
|
||||
|
||||
/// This is a type which instance is referenced by relevant users
|
||||
/// (types) of the type system, so that we can know when the type
|
||||
/// system is 'used' or not.
|
||||
///
|
||||
/// It can then serve to detect when the type system is not used
|
||||
/// anymore, so that resources that should stay live only during the
|
||||
/// life time of *users* of the type system can be deallocated.
|
||||
///
|
||||
/// A kind of canary in a coal mine, so to speak.
|
||||
class usage_watchdog
|
||||
{};
|
||||
|
||||
/// A convenience typedef for a shared pointer to @ref usage_watchdog.
|
||||
typedef shared_ptr<usage_watchdog> usage_watchdog_sptr;
|
||||
|
||||
/// A convenience typedef for a weak pointer to @ref usage_watchdog.
|
||||
typedef weak_ptr<usage_watchdog> usage_watchdog_wptr;
|
||||
|
||||
/// Getter of the usage watchdog.
|
||||
///
|
||||
/// Note that this getter does *not* increment the usage count of the
|
||||
/// watchdog.
|
||||
///
|
||||
/// @return a reference on the usage watchdog.
|
||||
static usage_watchdog_sptr&
|
||||
get_usage_watchdog()
|
||||
{
|
||||
static usage_watchdog_sptr watchdog;
|
||||
return watchdog;
|
||||
}
|
||||
|
||||
/// Getter of a weak pointer to the usage watchdog.
|
||||
///
|
||||
/// This weak pointer on the usage watchdog allows users to test if
|
||||
/// the usage watchdog is referenced by someone else or not. This
|
||||
/// test is done via the method weak_ptr::expired(). What a wonderful
|
||||
/// method ...
|
||||
///
|
||||
/// @return a reference to the weak pointer to the usage watchdog.
|
||||
static usage_watchdog_wptr&
|
||||
get_usage_watchdog_wptr()
|
||||
{
|
||||
static usage_watchdog_wptr watchdog;
|
||||
return watchdog;
|
||||
}
|
||||
|
||||
/// Increase the reference count of the usage watchdog.
|
||||
///
|
||||
/// Actually this function returns a shared pointer to the usage
|
||||
/// pointer. Storing that shared pointer is what increases the
|
||||
/// reference count of the watchdog. When the shared pointer that
|
||||
/// stores the returned usage watchdog is destroyed, the reference
|
||||
/// count goes down.
|
||||
///
|
||||
/// @return a shared pointer to the usage watchdog so that its
|
||||
/// reference count can be increased by the simple fact of storing it.
|
||||
static usage_watchdog_sptr
|
||||
ref_usage_watchdog()
|
||||
{
|
||||
usage_watchdog_sptr result;
|
||||
if (!get_usage_watchdog())
|
||||
{
|
||||
usage_watchdog_sptr w(new usage_watchdog);
|
||||
get_usage_watchdog() = w;
|
||||
get_usage_watchdog_wptr() = w;
|
||||
}
|
||||
result = get_usage_watchdog();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/// Test if the reference count of the usage watchdog shared point
|
||||
/// reached zero. If yes, cleanup the data of the type system that is
|
||||
/// supposed to stay live only as long as the usage watchdog shared
|
||||
/// pointer is live.
|
||||
static void
|
||||
maybe_cleanup_type_system_data()
|
||||
{
|
||||
if (!get_usage_watchdog_wptr().expired())
|
||||
get_canonical_types_map().clear();
|
||||
}
|
||||
|
||||
/// @brief the location of a token represented in its simplest form.
|
||||
/// Instances of this type are to be stored in a sorted vector, so the
|
||||
/// type must have proper relational operators.
|
||||
@@ -159,6 +249,7 @@ typedef unordered_map<function_type_sptr,
|
||||
/// Private type to hold private members of @ref translation_unit
|
||||
struct translation_unit::priv
|
||||
{
|
||||
usage_watchdog_sptr usage_watchdog_;
|
||||
bool is_constructed_;
|
||||
char address_size_;
|
||||
std::string path_;
|
||||
@@ -169,7 +260,30 @@ struct translation_unit::priv
|
||||
priv()
|
||||
: is_constructed_(),
|
||||
address_size_()
|
||||
{}
|
||||
{
|
||||
// Note that translation units own types.
|
||||
//
|
||||
// There is data in the type system that is global and that should
|
||||
// have the same lifetime as the type system itself. So when the
|
||||
// type system has no more users, its global data should be
|
||||
// de-allocated.
|
||||
//
|
||||
// So let's say that we are using the type system. We say this by
|
||||
// increasing the reference count of the shared pointer to the
|
||||
// usage watchdog of the type system. When that ref-count goes to
|
||||
// zero, that means the type system has no more use. At that
|
||||
// point the global data of the type system needs to be
|
||||
// de-allocated. This is done in the destructor of this
|
||||
// translation_unit::priv type.
|
||||
usage_watchdog_ = ref_usage_watchdog();
|
||||
}
|
||||
|
||||
~priv()
|
||||
{
|
||||
// So when the translation unit is de-allocated, let's de-allocate
|
||||
// type system data that should not outlive translation units.
|
||||
maybe_cleanup_type_system_data();
|
||||
}
|
||||
}; // end translation_unit::priv
|
||||
|
||||
// <translation_unit stuff>
|
||||
@@ -4638,8 +4752,8 @@ struct type_base::priv
|
||||
///
|
||||
/// @return the map that contains the canonical types of all the types
|
||||
/// known the running instance of libabigail in a given process.
|
||||
type_base::canonical_types_map_type&
|
||||
type_base::get_canonical_types_map()
|
||||
static canonical_types_map_type&
|
||||
get_canonical_types_map()
|
||||
{
|
||||
static canonical_types_map_type m;
|
||||
return m;
|
||||
|
||||
+39
-111
@@ -737,8 +737,7 @@ public:
|
||||
};// end class read_context
|
||||
|
||||
static int advance_cursor(read_context&);
|
||||
static bool read_translation_unit_from_input(read_context&,
|
||||
translation_unit&);
|
||||
static translation_unit_sptr read_translation_unit_from_input(read_context&);
|
||||
static bool read_symbol_db_from_input(read_context&, bool,
|
||||
string_elf_symbols_map_sptr&);
|
||||
static bool read_location(read_context&, xmlNodePtr, location&);
|
||||
@@ -999,16 +998,16 @@ walk_xml_node_to_map_type_ids(read_context& ctxt,
|
||||
///
|
||||
/// @param ctxt the current input context
|
||||
///
|
||||
/// @param tu the translation unit resulting from the parsing.
|
||||
///
|
||||
/// @return true upon successful parsing, false otherwise.
|
||||
static bool
|
||||
read_translation_unit_from_input(read_context& ctxt,
|
||||
translation_unit& tu)
|
||||
/// @return the translation unit resulting from the parsing upon
|
||||
/// successful completion, or nil.
|
||||
static translation_unit_sptr
|
||||
read_translation_unit_from_input(read_context& ctxt)
|
||||
{
|
||||
translation_unit_sptr tu, nil;
|
||||
|
||||
xml::reader_sptr reader = ctxt.get_reader();
|
||||
if (!reader)
|
||||
return false;
|
||||
return nil;
|
||||
|
||||
// The document must start with the abi-instr node.
|
||||
int status = 1;
|
||||
@@ -1018,28 +1017,30 @@ read_translation_unit_from_input(read_context& ctxt,
|
||||
|
||||
if (status != 1 || !xmlStrEqual (XML_READER_GET_NODE_NAME(reader).get(),
|
||||
BAD_CAST("abi-instr")))
|
||||
return false;
|
||||
return nil;
|
||||
|
||||
xmlNodePtr node = xmlTextReaderExpand(reader.get());
|
||||
if (!node)
|
||||
return false;
|
||||
return nil;
|
||||
|
||||
tu.reset(new translation_unit(""));
|
||||
|
||||
xml::xml_char_sptr addrsize_str =
|
||||
XML_NODE_GET_ATTRIBUTE(node, "address-size");
|
||||
if (addrsize_str)
|
||||
{
|
||||
char address_size = atoi(reinterpret_cast<char*>(addrsize_str.get()));
|
||||
tu.set_address_size(address_size);
|
||||
tu->set_address_size(address_size);
|
||||
}
|
||||
|
||||
xml::xml_char_sptr path_str = XML_NODE_GET_ATTRIBUTE(node, "path");
|
||||
if (path_str)
|
||||
tu.set_path(reinterpret_cast<char*>(path_str.get()));
|
||||
tu->set_path(reinterpret_cast<char*>(path_str.get()));
|
||||
|
||||
// We are at global scope, as we've just seen the top-most
|
||||
// "abi-instr" element.
|
||||
ctxt.push_decl(tu.get_global_scope());
|
||||
ctxt.map_xml_node_to_decl(node, tu.get_global_scope());
|
||||
ctxt.push_decl(tu->get_global_scope());
|
||||
ctxt.map_xml_node_to_decl(node, tu->get_global_scope());
|
||||
|
||||
walk_xml_node_to_map_type_ids(ctxt, node);
|
||||
|
||||
@@ -1055,7 +1056,7 @@ read_translation_unit_from_input(read_context& ctxt,
|
||||
|
||||
ctxt.clear_per_translation_unit_data();
|
||||
|
||||
return true;
|
||||
return tu;
|
||||
}
|
||||
|
||||
/// Parse the input XML document containing a function symbols
|
||||
@@ -1282,8 +1283,8 @@ read_corpus_from_input(read_context& ctxt)
|
||||
// Read the translation units.
|
||||
do
|
||||
{
|
||||
translation_unit_sptr tu(new translation_unit(""));
|
||||
is_ok = read_translation_unit_from_input(ctxt, *tu);
|
||||
translation_unit_sptr tu = read_translation_unit_from_input(ctxt);
|
||||
is_ok = tu;
|
||||
if (is_ok)
|
||||
corp.add(tu);
|
||||
}
|
||||
@@ -1300,44 +1301,28 @@ read_corpus_from_input(read_context& ctxt)
|
||||
/// @param input_file a path to the file containing the xml document
|
||||
/// to parse.
|
||||
///
|
||||
/// @param tu the translation unit resulting from the parsing.
|
||||
///
|
||||
/// @return true upon successful parsing, false otherwise.
|
||||
bool
|
||||
read_translation_unit_from_file(const string& input_file,
|
||||
translation_unit& tu)
|
||||
/// @return the translation unit resulting from the parsing upon
|
||||
/// successful completion, or nil.
|
||||
translation_unit_sptr
|
||||
read_translation_unit_from_file(const string& input_file)
|
||||
{
|
||||
read_context read_ctxt(xml::new_reader_from_file(input_file));
|
||||
return read_translation_unit_from_input(read_ctxt, tu);
|
||||
return read_translation_unit_from_input(read_ctxt);
|
||||
}
|
||||
|
||||
/// Parse an ABI instrumentation file (in XML format) at a given path.
|
||||
/// The path used is the one associated to the instance of @ref
|
||||
/// translation_unit.
|
||||
///
|
||||
/// @param tu the translation unit to populate with the de-serialized
|
||||
/// from of what is read at translation_unit::get_path().
|
||||
///
|
||||
/// @return true upon successful parsing, false otherwise.
|
||||
bool
|
||||
read_translation_unit_from_file(translation_unit& tu)
|
||||
{return read_translation_unit_from_file(tu.get_path(), tu);}
|
||||
|
||||
/// Parse an ABI instrumentation file (in XML format) from an
|
||||
/// in-memory buffer.
|
||||
///
|
||||
/// @param buffer the in-memory buffer containing the xml document to
|
||||
/// parse.
|
||||
///
|
||||
/// @param tu the translation unit resulting from the parsing.
|
||||
///
|
||||
/// @return true upon successful parsing, false otherwise.
|
||||
bool
|
||||
read_translation_unit_from_buffer(const string& buffer,
|
||||
translation_unit& tu)
|
||||
/// @return the translation unit resulting from the parsing upon
|
||||
/// successful completion, or nil.
|
||||
translation_unit_sptr
|
||||
read_translation_unit_from_buffer(const string& buffer)
|
||||
{
|
||||
read_context read_ctxt(xml::new_reader_from_buffer(buffer));
|
||||
return read_translation_unit_from_input(read_ctxt, tu);
|
||||
return read_translation_unit_from_input(read_ctxt);
|
||||
}
|
||||
|
||||
/// This function is called by @ref read_translation_unit_from_input.
|
||||
@@ -3847,68 +3832,14 @@ handle_class_tdecl(read_context& ctxt,
|
||||
///
|
||||
/// @param in a pointer to the input stream.
|
||||
///
|
||||
/// @param tu the translation unit resulting from the parsing. This
|
||||
/// is populated iff the function returns true.
|
||||
///
|
||||
/// @return true upon successful parsing, false otherwise.
|
||||
bool
|
||||
read_translation_unit_from_istream(istream* in,
|
||||
translation_unit& tu)
|
||||
{
|
||||
read_context read_ctxt(xml::new_reader_from_istream(in));
|
||||
return read_translation_unit_from_input(read_ctxt, tu);
|
||||
}
|
||||
|
||||
/// De-serialize a translation unit from an ABI Instrumentation xml
|
||||
/// file coming from an input stream.
|
||||
///
|
||||
/// @param in a pointer to the input stream.
|
||||
///
|
||||
/// @return a pointer to the resulting translation unit.
|
||||
/// @return the translation unit resulting from the parsing upon
|
||||
/// successful completion, or nil.
|
||||
translation_unit_sptr
|
||||
read_translation_unit_from_istream(istream* in)
|
||||
{
|
||||
translation_unit_sptr result(new translation_unit(""));
|
||||
if (!read_translation_unit_from_istream(in, *result))
|
||||
return translation_unit_sptr();
|
||||
return result;
|
||||
read_context read_ctxt(xml::new_reader_from_istream(in));
|
||||
return read_translation_unit_from_input(read_ctxt);
|
||||
}
|
||||
|
||||
/// De-serialize a translation unit from an ABI Instrumentation XML
|
||||
/// file at a given path.
|
||||
///
|
||||
/// @param file_path the path to the ABI Instrumentation XML file.
|
||||
///
|
||||
/// @return the deserialized translation or NULL if file_path could
|
||||
/// not be read. If file_path contains nothing, a non-null
|
||||
/// translation_unit is returned, but with empty content.
|
||||
translation_unit_sptr
|
||||
read_translation_unit_from_file(const string& file_path)
|
||||
{
|
||||
translation_unit_sptr result(new translation_unit(file_path));
|
||||
|
||||
if (!xml_reader::read_translation_unit_from_file(result->get_path(), *result))
|
||||
return translation_unit_sptr();
|
||||
return result;
|
||||
}
|
||||
|
||||
/// De-serialize a translation unit from an in-memory buffer
|
||||
/// containing and ABI Instrumentation XML content.
|
||||
///
|
||||
/// @param buffer the buffer containing the ABI Instrumentation XML
|
||||
/// content to parse.
|
||||
///
|
||||
/// @return the deserialized translation.
|
||||
translation_unit_sptr
|
||||
read_translation_unit_from_buffer(const std::string& buffer)
|
||||
{
|
||||
translation_unit_sptr result(new translation_unit(""));
|
||||
|
||||
if (!xml_reader::read_translation_unit_from_buffer(buffer, *result))
|
||||
return translation_unit_sptr();
|
||||
return result;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
struct array_deleter
|
||||
{
|
||||
@@ -3933,17 +3864,17 @@ struct array_deleter
|
||||
/// read from the zip archive.
|
||||
///
|
||||
/// @return true upon successful completion, false otherwise.
|
||||
static bool
|
||||
read_to_translation_unit(translation_unit& tu,
|
||||
zip_sptr ar,
|
||||
static translation_unit_sptr
|
||||
read_to_translation_unit(zip_sptr ar,
|
||||
int file_index)
|
||||
{
|
||||
translation_unit_sptr nil;
|
||||
if (!ar)
|
||||
return false;
|
||||
return nil;
|
||||
|
||||
zip_file_sptr f = open_file_in_archive(ar, file_index);
|
||||
if (!f)
|
||||
return false;
|
||||
return nil;
|
||||
|
||||
string input;
|
||||
{
|
||||
@@ -3960,10 +3891,7 @@ read_to_translation_unit(translation_unit& tu,
|
||||
}
|
||||
}
|
||||
|
||||
if (!read_translation_unit_from_buffer(input, tu))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
return read_translation_unit_from_buffer(input);
|
||||
}
|
||||
|
||||
/// Read an ABI corpus from an archive file which is a ZIP archive of
|
||||
|
||||
@@ -118,18 +118,18 @@ main(int argc, char* argv[])
|
||||
dwarf_reader::status c1_status, c2_status;
|
||||
corpus_sptr c1, c2;
|
||||
|
||||
c1_status = dwarf_reader::read_corpus_from_elf(opts.elf1, 0,
|
||||
/*load_all_types=*/false,
|
||||
c1);
|
||||
c1 = dwarf_reader::read_corpus_from_elf(opts.elf1, 0,
|
||||
/*load_all_types=*/false,
|
||||
c1_status);
|
||||
if (c1_status != dwarf_reader::STATUS_OK)
|
||||
{
|
||||
cerr << "Failed to read elf file " << opts.elf1 << "\n";
|
||||
return 1;
|
||||
}
|
||||
|
||||
c2_status = dwarf_reader::read_corpus_from_elf(opts.elf2, 0,
|
||||
/*load_all_types=*/false,
|
||||
c2);
|
||||
c2 = dwarf_reader::read_corpus_from_elf(opts.elf2, 0,
|
||||
/*load_all_types=*/false,
|
||||
c2_status);
|
||||
if (c2_status != dwarf_reader::STATUS_OK)
|
||||
{
|
||||
cerr << "Failed to read elf file " << opts.elf2 << "\n";
|
||||
|
||||
@@ -253,7 +253,6 @@ main()
|
||||
bool is_ok = true;
|
||||
string in_elfv0_path, in_elfv1_path,
|
||||
ref_diff_report_path, out_diff_report_path;
|
||||
abigail::corpus_sptr corp0, corp1;
|
||||
|
||||
for (InOutSpec* s = in_out_specs; s->in_elfv0_path; ++s)
|
||||
{
|
||||
@@ -269,14 +268,20 @@ main()
|
||||
continue;
|
||||
}
|
||||
|
||||
read_corpus_from_elf(in_elfv0_path,
|
||||
/*debug_info_root_path=*/0,
|
||||
/*load_all_types=*/false,
|
||||
corp0);
|
||||
read_corpus_from_elf(in_elfv1_path,
|
||||
/*debug_info_root_path=*/0,
|
||||
/*load_all_types=*/false,
|
||||
corp1);
|
||||
abigail::dwarf_reader::status status =
|
||||
abigail::dwarf_reader::STATUS_UNKNOWN;
|
||||
|
||||
abigail::corpus_sptr corp0 =
|
||||
read_corpus_from_elf(in_elfv0_path,
|
||||
/*debug_info_root_path=*/0,
|
||||
/*load_all_types=*/false,
|
||||
status);
|
||||
|
||||
abigail::corpus_sptr corp1 =
|
||||
read_corpus_from_elf(in_elfv1_path,
|
||||
/*debug_info_root_path=*/0,
|
||||
/*load_all_types=*/false,
|
||||
status);
|
||||
|
||||
if (!corp0)
|
||||
{
|
||||
@@ -284,6 +289,7 @@ main()
|
||||
is_ok = false;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!corp1)
|
||||
{
|
||||
cerr << "failed to read " << in_elfv1_path << "\n";
|
||||
|
||||
@@ -136,13 +136,13 @@ main(int argc, char **argv)
|
||||
|
||||
string file_name = argv[1];
|
||||
|
||||
abigail::translation_unit tu(file_name);
|
||||
if (!abigail::xml_reader::read_translation_unit_from_file(tu))
|
||||
abigail::translation_unit_sptr tu;
|
||||
if (!(tu = abigail::xml_reader::read_translation_unit_from_file(file_name)))
|
||||
{
|
||||
cerr << "failed to read " << file_name << "\n";
|
||||
return 1;
|
||||
}
|
||||
|
||||
name_printing_visitor v;
|
||||
tu.traverse(v);
|
||||
tu->traverse(v);
|
||||
}
|
||||
|
||||
@@ -111,10 +111,12 @@ main()
|
||||
for (InOutSpec* s = in_out_specs; s->in_elf_path; ++s)
|
||||
{
|
||||
in_elf_path = abigail::tests::get_src_dir() + "/tests/" + s->in_elf_path;
|
||||
abigail::dwarf_reader::read_corpus_from_elf(in_elf_path,
|
||||
/*debug_info_root_path=*/0,
|
||||
/*load_all_types=*/false,
|
||||
corp);
|
||||
abigail::dwarf_reader::status status =
|
||||
abigail::dwarf_reader::STATUS_UNKNOWN;
|
||||
corp = abigail::dwarf_reader::read_corpus_from_elf(in_elf_path,
|
||||
/*debug_info_root_path=*/0,
|
||||
/*load_all_types=*/false,
|
||||
status);
|
||||
if (!corp)
|
||||
{
|
||||
cerr << "failed to read " << in_elf_path << "\n";
|
||||
|
||||
@@ -39,7 +39,7 @@ using std::cerr;
|
||||
using abigail::tools_utils::file_type;
|
||||
using abigail::tools_utils::check_file;
|
||||
using abigail::tools_utils::guess_file_type;
|
||||
using abigail::translation_unit;
|
||||
using abigail::translation_unit_sptr;
|
||||
using abigail::corpus_sptr;
|
||||
using abigail::xml_reader::read_translation_unit_from_file;
|
||||
using abigail::xml_reader::read_corpus_from_native_xml_file;
|
||||
@@ -186,13 +186,13 @@ main()
|
||||
if (!check_file(in_path, cerr))
|
||||
return true;
|
||||
|
||||
translation_unit tu(in_path);
|
||||
translation_unit_sptr tu;
|
||||
corpus_sptr corpus;
|
||||
|
||||
bool read = false;
|
||||
file_type t = guess_file_type(in_path);
|
||||
if (t == abigail::tools_utils::FILE_TYPE_NATIVE_BI)
|
||||
read = read_translation_unit_from_file(tu);
|
||||
read = (tu = read_translation_unit_from_file(in_path));
|
||||
else if (t == abigail::tools_utils::FILE_TYPE_XML_CORPUS)
|
||||
read = (corpus = read_corpus_from_native_xml_file(in_path));
|
||||
else
|
||||
@@ -226,7 +226,7 @@ main()
|
||||
if (t == abigail::tools_utils::FILE_TYPE_XML_CORPUS)
|
||||
r = write_corpus_to_native_xml(corpus, /*indent=*/0, of);
|
||||
else if (t == abigail::tools_utils::FILE_TYPE_NATIVE_BI)
|
||||
r = write_translation_unit(tu, /*indent=*/0, of);
|
||||
r = write_translation_unit(*tu, /*indent=*/0, of);
|
||||
else
|
||||
abort();
|
||||
|
||||
|
||||
+9
-10
@@ -604,13 +604,13 @@ main(int argc, char* argv[])
|
||||
}
|
||||
|
||||
// Read the application ELF file.
|
||||
corpus_sptr app_corpus;
|
||||
char * app_di_root = opts.app_di_root_path.get();
|
||||
status status =
|
||||
status status = abigail::dwarf_reader::STATUS_UNKNOWN;
|
||||
corpus_sptr app_corpus=
|
||||
read_corpus_from_elf(opts.app_path,
|
||||
&app_di_root,
|
||||
/*load_all_types=*/opts.weak_mode,
|
||||
app_corpus);
|
||||
status);
|
||||
|
||||
if (status & abigail::dwarf_reader::STATUS_NO_SYMBOLS_FOUND)
|
||||
{
|
||||
@@ -652,12 +652,11 @@ main(int argc, char* argv[])
|
||||
return abigail::tools_utils::ABIDIFF_ERROR;
|
||||
}
|
||||
|
||||
corpus_sptr lib1_corpus;
|
||||
char * lib1_di_root = opts.lib1_di_root_path.get();
|
||||
status = read_corpus_from_elf(opts.lib1_path,
|
||||
corpus_sptr lib1_corpus = read_corpus_from_elf(opts.lib1_path,
|
||||
&lib1_di_root,
|
||||
/*load_all_types=*/false,
|
||||
lib1_corpus);
|
||||
status);
|
||||
if (status & abigail::dwarf_reader::STATUS_DEBUG_INFO_NOT_FOUND)
|
||||
cerr << "could not read debug info for " << opts.lib1_path << "\n";
|
||||
if (status & abigail::dwarf_reader::STATUS_NO_SYMBOLS_FOUND)
|
||||
@@ -677,10 +676,10 @@ main(int argc, char* argv[])
|
||||
{
|
||||
assert(!opts.lib2_path.empty());
|
||||
char * lib2_di_root = opts.lib2_di_root_path.get();
|
||||
status = read_corpus_from_elf(opts.lib2_path,
|
||||
&lib2_di_root,
|
||||
/*load_all_types=*/false,
|
||||
lib2_corpus);
|
||||
lib2_corpus = read_corpus_from_elf(opts.lib2_path,
|
||||
&lib2_di_root,
|
||||
/*load_all_types=*/false,
|
||||
status);
|
||||
if (status & abigail::dwarf_reader::STATUS_DEBUG_INFO_NOT_FOUND)
|
||||
cerr << "could not read debug info for " << opts.lib2_path << "\n";
|
||||
if (status & abigail::dwarf_reader::STATUS_NO_SYMBOLS_FOUND)
|
||||
|
||||
+8
-10
@@ -532,11 +532,10 @@ main(int argc, char* argv[])
|
||||
case abigail::tools_utils::FILE_TYPE_ELF:
|
||||
case abigail::tools_utils::FILE_TYPE_AR:
|
||||
di_dir1 = opts.di_root_path1.get();
|
||||
c1_status =
|
||||
abigail::dwarf_reader::read_corpus_from_elf(opts.file1,
|
||||
&di_dir1,
|
||||
/*load_all_types=*/false,
|
||||
c1);
|
||||
c1 = abigail::dwarf_reader::read_corpus_from_elf(opts.file1,
|
||||
&di_dir1,
|
||||
/*load_all_types=*/false,
|
||||
c1_status);
|
||||
break;
|
||||
case abigail::tools_utils::FILE_TYPE_XML_CORPUS:
|
||||
c1 =
|
||||
@@ -561,11 +560,10 @@ main(int argc, char* argv[])
|
||||
case abigail::tools_utils::FILE_TYPE_ELF:
|
||||
case abigail::tools_utils::FILE_TYPE_AR:
|
||||
di_dir2 = opts.di_root_path2.get();
|
||||
c2_status =
|
||||
abigail::dwarf_reader::read_corpus_from_elf(opts.file2,
|
||||
&di_dir2,
|
||||
/*load_all_types=*/false,
|
||||
c2);
|
||||
c2 = abigail::dwarf_reader::read_corpus_from_elf(opts.file2,
|
||||
&di_dir2,
|
||||
/*load_all_types=*/false,
|
||||
c2_status);
|
||||
break;
|
||||
case abigail::tools_utils::FILE_TYPE_XML_CORPUS:
|
||||
c2 =
|
||||
|
||||
+2
-1
@@ -214,7 +214,8 @@ main(int argc, char* argv[])
|
||||
}
|
||||
}
|
||||
|
||||
dwarf_reader::status s = read_corpus_from_elf(ctxt, corp);
|
||||
dwarf_reader::status s = dwarf_reader::STATUS_UNKNOWN;
|
||||
corp = read_corpus_from_elf(ctxt, s);
|
||||
if (!corp)
|
||||
{
|
||||
if (s == dwarf_reader::STATUS_DEBUG_INFO_NOT_FOUND)
|
||||
|
||||
+2
-2
@@ -210,10 +210,10 @@ main(int argc, char* argv[])
|
||||
case abigail::tools_utils::FILE_TYPE_ELF:
|
||||
case abigail::tools_utils::FILE_TYPE_AR:
|
||||
di_root_path = opts.di_root_path.get();
|
||||
s= read_corpus_from_elf(opts.file_path,
|
||||
corp = read_corpus_from_elf(opts.file_path,
|
||||
&di_root_path,
|
||||
/*load_all_types=*/false,
|
||||
corp);
|
||||
s);
|
||||
break;
|
||||
case abigail::tools_utils::FILE_TYPE_XML_CORPUS:
|
||||
corp = read_corpus_from_native_xml_file(opts.file_path);
|
||||
|
||||
Reference in New Issue
Block a user