Merge tm-qpr-dev-plus-aosp-without-vendor@9467136
Bug: 264720040
Merged-In: Ic6ebbeef9109f7f5298846f13780b54e97c9503f
Change-Id: I03121534906305bac91a67dbfeb55083d3dc64fe
diff --git a/src/abg-dwarf-reader.cc b/src/abg-dwarf-reader.cc
index ccf3768..f476b3a 100644
--- a/src/abg-dwarf-reader.cc
+++ b/src/abg-dwarf-reader.cc
@@ -8364,7 +8364,7 @@
case DW_OP_bra:
val1 = ctxt.pop();
- if (val1 != 0)
+ if (val1.const_value() != 0)
index += val1.const_value() - 1;
break;
diff --git a/tools/abitidy.cc b/tools/abitidy.cc
index e2c7f65..4f65271 100644
--- a/tools/abitidy.cc
+++ b/tools/abitidy.cc
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
// -*- Mode: C++ -*-
//
-// Copyright (C) 2021-2022 Google, Inc.
+// Copyright (C) 2021 Google, Inc.
//
// Author: Giuliano Procida
@@ -23,6 +23,7 @@
#include <cstring>
#include <fstream>
#include <functional>
+#include <iomanip>
#include <ios>
#include <iostream>
#include <map>
@@ -469,7 +470,7 @@
///
/// @param report whether to report untyped symbols
///
-/// @param alias_map mapping from corpus to alias to main elf-symbol-id
+/// @param alias_map mapping from alias to main elf-symbol-id
///
/// @param root the XML root element
///
@@ -477,17 +478,15 @@
static size_t
handle_unreachable(
bool prune, bool report,
- const std::unordered_map<xmlNodePtr,
- std::unordered_map<std::string,
- std::string>>& alias_map,
+ const std::unordered_map<std::string, std::string>& alias_map,
xmlNodePtr root)
{
- // ELF symbol ids, per corpus.
- std::set<std::pair<xmlNodePtr, std::string>> elf_symbol_ids;
+ // ELF symbol ids.
+ std::set<std::string> elf_symbol_ids;
- // Simple way of allowing two kinds of nodes: nullptr=>type,
- // node=>symbol.
- using vertex_t = std::pair<xmlNodePtr, std::string>;
+ // Simple way of allowing two kinds of nodes: false=>type,
+ // true=>symbol.
+ using vertex_t = std::pair<bool, std::string>;
// Graph vertices.
std::set<vertex_t> vertices;
@@ -498,10 +497,6 @@
// containing and refers-to relationships.
std::vector<vertex_t> stack;
- // Keep track of which corpus we are in as symbols and elf-symbol-ids are
- // scoped per corpus.
- xmlNodePtr current_corpus = nullptr;
-
// Process an XML node, adding a vertex and possibly some edges.
std::function<void(xmlNodePtr)> process_node = [&](xmlNodePtr node) {
// We only care about elements and not comments, at this stage.
@@ -510,15 +505,10 @@
const char* node_name = from_libxml(node->name);
- // Is this a corpus?
- if (strcmp(node_name, "abi-corpus") == 0)
- current_corpus = node;
-
// Is this an ELF symbol?
if (strcmp(node_name, "elf-symbol") == 0)
{
- elf_symbol_ids.insert(
- std::make_pair(current_corpus, get_elf_symbol_id(node)));
+ elf_symbol_ids.insert(get_elf_symbol_id(node));
// Early return is safe, but not necessary.
return;
}
@@ -529,7 +519,7 @@
: std::optional<std::string>();
if (id)
{
- vertex_t type_vertex{nullptr, id.value()};
+ vertex_t type_vertex{false, id.value()};
vertices.insert(type_vertex);
const auto naming_typedef_id = get_attribute(node, "naming-typedef-id");
if (naming_typedef_id)
@@ -539,7 +529,7 @@
// option will drop these, but if they are still present, we
// should model the link to avoid the risk of dangling
// references.
- vertex_t naming_typedef_vertex{nullptr, naming_typedef_id.value()};
+ vertex_t naming_typedef_vertex{false, naming_typedef_id.value()};
edges[type_vertex].insert(naming_typedef_vertex);
}
if (!stack.empty())
@@ -558,7 +548,7 @@
const auto symbol = get_attribute(node, "elf-symbol-id");
if (symbol)
{
- vertex_t symbol_vertex{current_corpus, symbol.value()};
+ vertex_t symbol_vertex{true, symbol.value()};
vertices.insert(symbol_vertex);
if (!stack.empty())
{
@@ -591,7 +581,7 @@
{
// The enclosing type or symbol refers to another type.
const auto& parent = stack.back();
- vertex_t type_id_vertex{nullptr, type_id.value()};
+ vertex_t type_id_vertex{false, type_id.value()};
edges[parent].insert(type_id_vertex);
}
@@ -624,16 +614,12 @@
size_t untyped = 0;
// Traverse the graph, starting from the ELF symbols.
- for (const auto& [corpus, symbol_id] : elf_symbol_ids)
+ for (const auto& symbol_id : elf_symbol_ids)
{
- const auto corpus_it = alias_map.find(corpus);
- assert(corpus_it != alias_map.end());
- const auto& corpus_alias_map = corpus_it->second;
- const auto it = corpus_alias_map.find(symbol_id);
- const auto& mapped_symbol_id = it != corpus_alias_map.end()
- ? it->second : symbol_id;
-
- vertex_t symbol_vertex{corpus, mapped_symbol_id};
+ const auto it = alias_map.find(symbol_id);
+ const auto& mapped_symbol_id =
+ it != alias_map.end() ? it->second : symbol_id;
+ vertex_t symbol_vertex{true, mapped_symbol_id};
if (vertices.count(symbol_vertex))
{
dfs(symbol_vertex);
@@ -654,10 +640,6 @@
const char* node_name = from_libxml(node->name);
- // Is this a corpus?
- if (strcmp(node_name, "abi-corpus") == 0)
- current_corpus = node;
-
// Return if we know that this is a type to keep or drop in its
// entirety.
const auto id = strcmp(node_name, "subrange") != 0
@@ -665,7 +647,7 @@
: std::optional<std::string>();
if (id)
{
- if (!seen.count(vertex_t{nullptr, id.value()}))
+ if (!seen.count(vertex_t{false, id.value()}))
remove_element(node);
return;
}
@@ -677,7 +659,7 @@
|| strcmp(node_name, "function-decl") == 0)
{
const auto symbol = get_attribute(node, "elf-symbol-id");
- if (!(symbol && seen.count(vertex_t{current_corpus, symbol.value()})))
+ if (!(symbol && seen.count(vertex_t{true, symbol.value()})))
remove_element(node);
return;
}
@@ -1427,57 +1409,71 @@
return result;
}
-/// Determine whether an element contains an elf-symbol-id attribute.
-///
-/// @param node the node to examine recursively
-///
-/// @return whether or not an elf-symbol-id attribute was found
-static bool
-contains_elf_symbol_id(xmlNodePtr node)
-{
- if (node->type != XML_ELEMENT_NODE)
- return false;
- if (get_attribute(node, "elf-symbol-id"))
- return true;
- for (auto child : get_children(node))
- if (contains_elf_symbol_id(child))
- return true;
- return false;
-}
-
-/// Sort instrs into a corpus.
-///
-/// The given instrs (grouped by source corpus) are sorted and moved
-/// into the destination corpus, except that elements containing
-/// symbol-linked declarations are not moved between corpora.
+/// Sort namespaces, types and declarations.
///
/// This loses annotations (XML comments) on namespace-decl elements.
/// It would have been a fair amount of extra work to preserve them.
///
-/// @param where the XML abi-corpus element into which to move elements
-///
-/// @param instrs a list of pairs of containing corpus and XML abi-instr
-/// element out of which to move elements
+/// @param root the XML root element
static void
-sort_instrs_into_corpus(
- xmlNodePtr where,
- const std::vector<std::pair<xmlNodePtr, std::vector<xmlNodePtr>>>& instrs)
+sort_namespaces_types_and_declarations(xmlNodePtr root)
{
+ // There are (currently) 2 ABI formats we handle here.
+ //
+ // 1. An abi-corpus containing one or more abi-instr. In this case, we
+ // move all namespaces, types and declarations to a replacement
+ // abi-instr at the end of the abi-corpus. The existing abi-instr will
+ // then be confirmed as empty and removed.
+ //
+ // 2. An abi-corpus-group containing one or more abi-corpus each
+ // containing zero or more abi-instr (with at least one abi-instr
+ // altogether). In this case the replacement abi-instr is created
+ // within the first abi-corpus of the group.
+ //
+ // Anything else is left alone. For example, single abi-instr elements
+ // are present in some libabigail test suite files.
+
+ // We first need to identify where to place the new abi-instr and
+ // collect all the abi-instr to process.
+ xmlNodePtr where = nullptr;
+ std::vector<xmlNodePtr> instrs;
+
+ auto process_corpus = [&](xmlNodePtr corpus) {
+ if (!where)
+ where = corpus;
+ for (auto instr : get_children(corpus))
+ if (strcmp(from_libxml(instr->name), "abi-instr") == 0)
+ instrs.push_back(instr);
+ };
+
+ const char* root_name = from_libxml(root->name);
+ if (strcmp(root_name, "abi-corpus-group") == 0)
+ {
+ // Process all corpora in a corpus group together.
+ for (auto corpus : get_children(root))
+ if (strcmp(from_libxml(corpus->name), "abi-corpus") == 0)
+ process_corpus(corpus);
+ }
+ else if (strcmp(root_name, "abi-corpus") == 0)
+ {
+ // We have a corpus to sort, just get its instrs.
+ process_corpus(root);
+ }
+
if (instrs.empty())
return;
// Collect the attributes of all the instrs.
std::map<std::string, std::set<std::string>> attributes;
- for (const auto& [corpus, corpus_instrs] : instrs)
- for (const auto& instr : corpus_instrs)
- for (auto p = instr->properties; p; p = p->next)
- {
- // This is horrible. There should be a better way of iterating.
- const char* attribute_name = from_libxml(p->name);
- const auto attribute_value = get_attribute(instr, attribute_name);
- assert(attribute_value);
- attributes[attribute_name].insert(attribute_value.value());
- }
+ for (auto instr : instrs)
+ for (auto p = instr->properties; p; p = p->next)
+ {
+ // This is horrible. There should be a better way of iterating.
+ const char* attribute_name = from_libxml(p->name);
+ const auto attribute_value = get_attribute(instr, attribute_name);
+ assert(attribute_value);
+ attributes[attribute_name].insert(attribute_value.value());
+ }
// Create and attach a replacement instr and populate its attributes.
xmlNodePtr replacement =
@@ -1537,18 +1533,7 @@
};
// Collect the child elements of all the instrs, by namespace scope.
- std::map<namespace_scope, std::vector<xmlNodePtr>> scoped_children;
- std::unordered_map<xmlNodePtr, xmlNodePtr> child_corpus;
- for (const auto& [corpus, corpus_instrs] : instrs)
- for (const auto& [scope, children] : get_children_by_namespace(corpus_instrs))
- {
- auto& these_scoped_children = scoped_children[scope];
- for (auto child : children)
- {
- these_scoped_children.push_back(child);
- child_corpus[child] = corpus;
- }
- }
+ auto scoped_children = get_children_by_namespace(instrs);
for (auto& [scope, children] : scoped_children)
// Sort the children, preserving order of duplicates.
std::stable_sort(children.begin(), children.end(), Compare());
@@ -1574,93 +1559,20 @@
return insertion.first->second;
};
- // Move each child to the replacement instr or namespace subelement
- // thereof, unless the child would move between corpora and is or
- // contains a symbol-linked declaration.
+ // Move the children to the replacement instr or its subelements.
for (const auto& [scope, elements] : scoped_children)
{
xmlNodePtr namespace_element = get_namespace_element(scope);
for (auto element : elements)
- if (child_corpus[element] == where || !contains_elf_symbol_id(element))
- move_element(element, namespace_element);
+ move_element(element, namespace_element);
}
- // Remove each original instr if now effectively empty.
- for (const auto& [corpus, corpus_instrs] : instrs)
- for (auto instr : corpus_instrs)
- if (get_children_by_namespace({instr}).empty())
- remove_node(instr);
-
- // Remove the replacement if it wasn't used.
- if (get_children(replacement).empty())
- remove_node(replacement);
-}
-
-/// Get corpora instrs.
-///
-/// @param corpora a vector of corpus elements
-///
-/// @return a vector of pairs of corpus and contained instr elements
-std::vector<std::pair<xmlNodePtr, std::vector<xmlNodePtr>>>
-get_corpora_instrs(const std::vector<xmlNodePtr>& corpora)
-{
- std::vector<std::pair<xmlNodePtr, std::vector<xmlNodePtr>>> result;
- for (auto corpus : corpora)
- {
- result.push_back({corpus, {}});
- auto& corpus_instrs = result.back().second;
- for (auto instr : get_children(corpus))
- if (strcmp(from_libxml(instr->name), "abi-instr") == 0)
- corpus_instrs.push_back(instr);
- }
- return result;
-}
-
-/// Sort namespaces, types and declarations.
-///
-/// @param root the XML root element
-static void
-sort_namespaces_types_and_declarations(xmlNodePtr root)
-{
- // There are (currently) 2 ABI formats we handle here.
- //
- // 1. An abi-corpus containing one or more abi-instr. In this case, we
- // move all namespaces, types and declarations to a replacement
- // abi-instr at the end of the abi-corpus.
- //
- // 2. An abi-corpus-group containing one or more abi-corpus each
- // containing zero or more abi-instr (with at least one abi-instr
- // altogether). In this case all the corpora are sorted together into
- // a replacement abi-instr created within the first corpus, except
- // that symbol-linked declarations in subsequent corpora are not moved.
- //
- // Anything else is left alone. For example, single abi-instr elements
- // are present in some libabigail test suite files.
-
- // We first need to identify where to place the new abi-instr and
- // collect all the abi-instr to process.
- const char* root_name = from_libxml(root->name);
- if (strcmp(root_name, "abi-corpus-group") == 0)
- {
- // Process all corpora in a corpus group together.
- std::vector<xmlNodePtr> corpora;
- xmlNodePtr first = nullptr;
- for (auto corpus : get_children(root))
- if (strcmp(from_libxml(corpus->name), "abi-corpus") == 0)
- {
- if (!first)
- first = corpus;
- corpora.push_back(corpus);
- }
- if (first)
- sort_instrs_into_corpus(first, get_corpora_instrs(corpora));
- // An extra pass to sort whatever may have been left behind.
- for (auto corpus : corpora)
- if (corpus != first)
- sort_instrs_into_corpus(corpus, get_corpora_instrs({corpus}));
- }
- else if (strcmp(root_name, "abi-corpus") == 0)
- sort_instrs_into_corpus(root, get_corpora_instrs({root}));
+ // Check the original instrs are now all empty and remove them.
+ for (auto instr : instrs)
+ if (get_children_by_namespace({instr}).empty())
+ remove_node(instr);
+ else
+ std::cerr << "original abi-instr has residual child elements\n";
}
static constexpr std::array<std::string_view, 2> SYMBOL_SECTION_SUFFICES = {
@@ -1809,14 +1721,10 @@
if (node->type != XML_ELEMENT_NODE)
return;
const char* node_name = from_libxml(node->name);
- if (strcmp(node_name, "abi-corpus-group") == 0)
- {
- std::cerr << "symbol processing must be per corpus\n";
- exit(1);
- }
- else if (strcmp(node_name, "abi-corpus") == 0
- || strcmp(node_name, "elf-variable-symbols") == 0
- || strcmp(node_name, "elf-function-symbols") == 0)
+ if (strcmp(node_name, "abi-corpus-group") == 0
+ || strcmp(node_name, "abi-corpus") == 0
+ || strcmp(node_name, "elf-variable-symbols") == 0
+ || strcmp(node_name, "elf-function-symbols") == 0)
{
// Process children.
for (auto child : get_children(node))
@@ -1884,18 +1792,17 @@
///
/// @param symbols the set of symbols
///
-/// @param corpus the XML corpus element
+/// @param root the XML root element
///
/// @return mapping from alias to main elf-symbol-id
std::unordered_map<std::string, std::string>
- filter_corpus_symbols(const std::optional<symbol_set>& symbols,
- xmlNodePtr corpus)
+ filter_symbols(const std::optional<symbol_set>& symbols, xmlNodePtr root)
{
// find symbols and record alias <-> main mappings
std::unordered_map<std::string, xmlNodePtr> symbol_map;
std::unordered_map<std::string, std::string> alias_map;
std::unordered_map<std::string, std::set<std::string>> main_map;
- process_symbols(symbol_map, alias_map, main_map, corpus);
+ process_symbols(symbol_map, alias_map, main_map, root);
// check that aliases and main symbols are disjoint
for (const auto& [alias, main] : alias_map)
if (alias_map.count(main))
@@ -1979,41 +1886,11 @@
}
}
- rewrite_symbols_in_declarations(mapping, corpus);
+ rewrite_symbols_in_declarations(mapping, root);
return alias_map;
}
-/// Remove unlisted ELF symbols.
-///
-/// @param symbols the set of symbols
-///
-/// @param root the XML root element
-///
-/// @return mapping from corpus to alias to main elf-symbol-id
-std::unordered_map<xmlNodePtr, std::unordered_map<std::string, std::string>>
- filter_symbols(const std::optional<symbol_set>& symbols, xmlNodePtr root)
-{
- std::unordered_map<xmlNodePtr, std::unordered_map<std::string, std::string>>
- result;
- const char* node_name = from_libxml(root->name);
- if (strcmp(node_name, "abi-corpus-group") == 0)
- {
- for (auto child : get_children(root))
- result[child] = filter_corpus_symbols(symbols, child);
- }
- else if (strcmp(node_name, "abi-corpus") == 0)
- {
- result[root] = filter_corpus_symbols(symbols, root);
- }
- else
- {
- std::cerr << "unexpected root element: " << node_name << '\n';
- exit(1);
- }
- return result;
-}
-
/// Main program.
///
/// Read and write ABI XML, with optional processing passes.
@@ -2207,7 +2084,7 @@
// Strip text nodes to simplify other operations.
strip_text(root);
- // Get corpus -> alias -> main mapping and remove unlisted symbols.
+ // Get alias -> main mapping and remove unlisted symbols.
const auto alias_map = filter_symbols(opt_symbols, root);
// Record type ids which correspond to anonymous types.