From: Dodji Seketeli Date: Thu, 31 Mar 2022 16:31:01 +0000 (+0200) Subject: abidw, dwarf-reader: Add an option to debug DIE canonicalization X-Git-Tag: libabigail-2.1~60 X-Git-Url: https://sourceware.org/git/?a=commitdiff_plain;h=b9c73978edd7737cbcdd8a809c1354bf21e67410;p=libabigail.git abidw, dwarf-reader: Add an option to debug DIE canonicalization While looking at something else, it appeared that I needed an option to turn on checks to debug DIE canonicalization. That option would itself be enable only when the project is configured using the --enable-debug-type-canonicalization configure option. * include/abg-ir.h (environment::debug_die_canonicalization_is_on): Declare new methods. * src/abg-ir.cc (environment::debug_die_canonicalization_is_on): Define them. * src/abg-dwarf-reader.cc (compare_dies_during_canonicalization): Define new static function. (read_context::{debug_die_canonicalization_is_on_, use_canonical_die_comparison_}): Declare these data members. (read_context::read_context): Initialize them. (read_context::get_canonical_die): When ODR is considered, if DIE canonicalization debugging is on, use the new compare_dies_during_canonicalization for the type comparison to be done both structurally and canonically; both comparison should yield the same result. Also, make this method function non-const. * src/abg-ir-priv.h (environment::priv::debug_die_canonicalization_): Define new data member. (environment::priv::priv): Initialize it. * tools/abidw.cc (options::debug_die_canonicalization_): Define new data member. (options::options): Initialize it. (display_usage): Add a description for the --debug-dc option. (parse_command): Parse the new --debug-dc option. (load_corpus_and_write_abixml): Use the new environment::debug_die_canonicalization_is_on. Signed-off-by: Dodji Seketeli --- diff --git a/include/abg-ir.h b/include/abg-ir.h index a2f4e1a7..3ca4d0a8 100644 --- a/include/abg-ir.h +++ b/include/abg-ir.h @@ -217,6 +217,12 @@ public: bool debug_type_canonicalization_is_on() const; + + void + debug_die_canonicalization_is_on(bool flag); + + bool + debug_die_canonicalization_is_on() const; #endif vector* get_canonical_types(const char* name); diff --git a/src/abg-dwarf-reader.cc b/src/abg-dwarf-reader.cc index 27dd4faf..d43364f1 100644 --- a/src/abg-dwarf-reader.cc +++ b/src/abg-dwarf-reader.cc @@ -541,6 +541,10 @@ compare_dies(const read_context& ctxt, const Dwarf_Die *l, const Dwarf_Die *r, bool update_canonical_dies_on_the_fly); +static bool +compare_dies_during_canonicalization(read_context& ctxt, + const Dwarf_Die *l, const Dwarf_Die *r, + bool update_canonical_dies_on_the_fly); /// Find the file name of the alternate debug info file. /// @@ -2136,6 +2140,10 @@ public: corpus::exported_decls_builder* exported_decls_builder_; options_type options_; bool drop_undefined_syms_; +#ifdef WITH_DEBUG_TYPE_CANONICALIZATION + bool debug_die_canonicalization_is_on_; + bool use_canonical_die_comparison_; +#endif read_context(); private: @@ -2279,6 +2287,11 @@ public: options_.load_in_linux_kernel_mode = linux_kernel_mode; options_.load_all_types = load_all_types; drop_undefined_syms_ = false; +#ifdef WITH_DEBUG_TYPE_CANONICALIZATION + debug_die_canonicalization_is_on_ = + environment->debug_die_canonicalization_is_on(); + use_canonical_die_comparison_ = true; +#endif load_in_linux_kernel_mode(linux_kernel_mode); } @@ -2861,7 +2874,7 @@ public: get_canonical_die(const Dwarf_Die *die, Dwarf_Die &canonical_die, size_t where, - bool die_as_type) const + bool die_as_type) { const die_source source = get_die_source(die); @@ -2915,6 +2928,29 @@ public: // ABG_ASSERT(i->second.size() == 1); Dwarf_Off canonical_die_offset = i->second.front(); get_die_from_offset(source, canonical_die_offset, &canonical_die); +#ifdef WITH_DEBUG_TYPE_CANONICALIZATION + if (debug_die_canonicalization_is_on_) + { + use_canonical_die_comparison_ = false; + bool structural_equality = + compare_dies(*this, &canonical_die, die, + /*update_canonical_dies_on_the_fly=*/false); + use_canonical_die_comparison_ = true; + if (!structural_equality) + { + std::cerr << "structural & canonical equality different for DIEs: " + << std::hex + << "l: " << canonical_die_offset + << ", r: " << die_offset + << std::dec + << ", repr: '" + << get_die_pretty_type_representation(&canonical_die, 0) + << "'" + << std::endl; + ABG_ASSERT_NOT_REACHED; + } + } +#endif set_canonical_die_offset(canonical_dies, die_offset, canonical_die_offset); @@ -2929,8 +2965,9 @@ public: cur_die_offset = *o; get_die_from_offset(source, cur_die_offset, &canonical_die); // compare die and canonical_die. - if (compare_dies(*this, die, &canonical_die, - /*update_canonical_dies_on_the_fly=*/true)) + if (compare_dies_during_canonicalization(const_cast(*this), + die, &canonical_die, + /*update_canonical_dies_on_the_fly=*/true)) { set_canonical_die_offset(canonical_dies, die_offset, @@ -3049,8 +3086,9 @@ public: Dwarf_Off die_offset = i->second[n]; get_die_from_offset(source, die_offset, &canonical_die); // compare die and canonical_die. - if (compare_dies(*this, die, &canonical_die, - /*update_canonical_dies_on_the_fly=*/true)) + if (compare_dies_during_canonicalization(const_cast(*this), + die, &canonical_die, + /*update_canonical_dies_on_the_fly=*/true)) { set_canonical_die_offset(canonical_dies, initial_die_offset, @@ -10745,6 +10783,60 @@ compare_dies(const read_context& ctxt, update_canonical_dies_on_the_fly); } +/// Compare two DIEs for the purpose of canonicalization. +/// +/// This is a sub-routine of read_context::get_canonical_die. +/// +/// When DIE canonicalization debugging is on, this function performs +/// both structural and canonical comparison. It expects that both +/// comparison yield the same result. +/// +/// @param ctxt the read context. +/// +/// @param l the left-hand-side comparison operand DIE. +/// +/// @param r the right-hand-side comparison operand DIE. +/// +/// @param update_canonical_dies_on_the_fly if true, then some +/// aggregate DIEs will see their canonical types propagated. +/// +/// @return true iff @p l equals @p r. +static bool +compare_dies_during_canonicalization(read_context& ctxt, + const Dwarf_Die *l, + const Dwarf_Die *r, + bool update_canonical_dies_on_the_fly) +{ +#ifdef WITH_DEBUG_TYPE_CANONICALIZATION + if (ctxt.debug_die_canonicalization_is_on_) + { + bool canonical_equality = false, structural_equality = false; + ctxt.use_canonical_die_comparison_ = false; + structural_equality = compare_dies(ctxt, l, r, + /*update_canonical_dies_on_the_fly=*/false); + ctxt.use_canonical_die_comparison_ = true; + canonical_equality = compare_dies(ctxt, l, r, + update_canonical_dies_on_the_fly); + if (canonical_equality != structural_equality) + { + std::cerr << "structural & canonical equality different for DIEs: " + << std::hex + << "l: " << dwarf_dieoffset(const_cast(l)) + << ", r: " << dwarf_dieoffset(const_cast(r)) + << std::dec + << ", repr: '" + << ctxt.get_die_pretty_type_representation(l, 0) + << "'" + << std::endl; + ABG_ASSERT_NOT_REACHED; + } + return structural_equality; + } +#endif + return compare_dies(ctxt, l, r, + update_canonical_dies_on_the_fly); +} + // ---------------------------------- // // --------------------------------- diff --git a/src/abg-ir-priv.h b/src/abg-ir-priv.h index a01a1b2c..f04266a8 100644 --- a/src/abg-ir-priv.h +++ b/src/abg-ir-priv.h @@ -403,6 +403,7 @@ struct environment::priv // result, otherwise, canonicalization is "broken" for that // particular type. bool debug_type_canonicalization_; + bool debug_die_canonicalization_; #endif priv() @@ -417,7 +418,8 @@ struct environment::priv #ifdef WITH_DEBUG_TYPE_CANONICALIZATION , use_canonical_type_comparison_(true), - debug_type_canonicalization_(false) + debug_type_canonicalization_(false), + debug_die_canonicalization_(false) #endif {} diff --git a/src/abg-ir.cc b/src/abg-ir.cc index 717c195d..bdeec162 100644 --- a/src/abg-ir.cc +++ b/src/abg-ir.cc @@ -3652,6 +3652,24 @@ environment::debug_type_canonicalization_is_on(bool flag) bool environment::debug_type_canonicalization_is_on() const {return priv_->debug_type_canonicalization_;} + +/// Setter of the "DIE canonicalization debugging" mode, triggered by +/// using the command: "abidw --debug-dc". +/// +/// @param flag true iff the DIE canonicalization debugging mode is +/// enabled. +void +environment::debug_die_canonicalization_is_on(bool flag) +{priv_->debug_die_canonicalization_ = flag;} + +/// Getter of the "DIE canonicalization debugging" mode, triggered by +/// using the command: "abidw --debug-dc". +/// +/// @return true iff the DIE canonicalization debugging mode is +/// enabled. +bool +environment::debug_die_canonicalization_is_on() const +{return priv_->debug_die_canonicalization_;} #endif // WITH_DEBUG_TYPE_CANONICALIZATION /// Get the vector of canonical types which have a given "string diff --git a/tools/abidw.cc b/tools/abidw.cc index 1ca642bb..174f084a 100644 --- a/tools/abidw.cc +++ b/tools/abidw.cc @@ -108,6 +108,7 @@ struct options #endif #ifdef WITH_DEBUG_TYPE_CANONICALIZATION bool debug_type_canonicalization; + bool debug_die_canonicalization; #endif bool annotate; bool do_log; @@ -145,6 +146,7 @@ struct options #endif #ifdef WITH_DEBUG_TYPE_CANONICALIZATION debug_type_canonicalization(), + debug_die_canonicalization(), #endif annotate(), do_log(), @@ -212,6 +214,7 @@ display_usage(const string& prog_name, ostream& out) #endif #ifdef WITH_DEBUG_TYPE_CANONICALIZATION << " --debug-tc debug the type canonicalization process\n" + << " --debug-dc debug the DIE canonicalization process\n" #endif #ifdef WITH_CTF << " --ctf use CTF instead of DWARF in ELF files\n" @@ -380,6 +383,9 @@ parse_command_line(int argc, char* argv[], options& opts) else if (!strcmp(argv[i], "--debug-tc") || !strcmp(argv[i], "debug-type-canonicalization")) opts.debug_type_canonicalization = true; + else if (!strcmp(argv[i], "--debug-dc") + || !strcmp(argv[i], "debug-die-canonicalization")) + opts.debug_die_canonicalization = true; #endif else if (!strcmp(argv[i], "--annotate")) opts.annotate = true; @@ -530,6 +536,8 @@ load_corpus_and_write_abixml(char* argv[], #ifdef WITH_DEBUG_TYPE_CANONICALIZATION if (opts.debug_type_canonicalization) env->debug_type_canonicalization_is_on(true); + if (opts.debug_die_canonicalization) + env->debug_die_canonicalization_is_on(true); #endif // First of all, read a libabigail IR corpus from the file specified