From: Sami Tolvanen <samitolvanen@google.com>
To: Masahiro Yamada <masahiroy@kernel.org>,
Luis Chamberlain <mcgrof@kernel.org>,
Miguel Ojeda <ojeda@kernel.org>,
Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: Matthew Maurer <mmaurer@google.com>,
Alex Gaynor <alex.gaynor@gmail.com>,
Wedson Almeida Filho <wedsonaf@gmail.com>,
Gary Guo <gary@garyguo.net>,
linux-kbuild@vger.kernel.org, linux-kernel@vger.kernel.org,
linux-modules@vger.kernel.org, rust-for-linux@vger.kernel.org,
Sami Tolvanen <samitolvanen@google.com>
Subject: [PATCH 10/15] gendwarfksyms: Expand structure types
Date: Mon, 17 Jun 2024 17:58:29 +0000 [thread overview]
Message-ID: <20240617175818.58219-27-samitolvanen@google.com> (raw)
In-Reply-To: <20240617175818.58219-17-samitolvanen@google.com>
Recursively expand DWARF structure types, e.g. structs, unions, and
enums. Type strings also encode structure member layout, which allows
us to determine ABI breakages if the compiler decides to reorder
members or otherwise change the layout.
Example output with --debug:
subprogram(
formal_parameter pointer_type *mut &str {
structure_type &str {
member pointer_type <unnamed> {
base_type u8 byte_size(1)
} data_member_location(0),
member base_type usize byte_size(8) data_member_location(8),
} byte_size(16) alignment(8)
},
)
-> base_type void;
Signed-off-by: Sami Tolvanen <samitolvanen@google.com>
---
tools/gendwarfksyms/gendwarfksyms.h | 5 ++
tools/gendwarfksyms/types.c | 127 +++++++++++++++++++++++++++-
2 files changed, 130 insertions(+), 2 deletions(-)
diff --git a/tools/gendwarfksyms/gendwarfksyms.h b/tools/gendwarfksyms/gendwarfksyms.h
index 03d8a4a039c3..4646eaf5c85e 100644
--- a/tools/gendwarfksyms/gendwarfksyms.h
+++ b/tools/gendwarfksyms/gendwarfksyms.h
@@ -52,8 +52,13 @@ extern bool no_pretty_print;
})
/* Consistent aliases (DW_TAG_<type>_type) for DWARF tags */
+#define DW_TAG_enumerator_type DW_TAG_enumerator
#define DW_TAG_formal_parameter_type DW_TAG_formal_parameter
+#define DW_TAG_member_type DW_TAG_member
+#define DW_TAG_template_type_parameter_type DW_TAG_template_type_parameter
#define DW_TAG_typedef_type DW_TAG_typedef
+#define DW_TAG_variant_part_type DW_TAG_variant_part
+#define DW_TAG_variant_type DW_TAG_variant
/*
* symbols.c
diff --git a/tools/gendwarfksyms/types.c b/tools/gendwarfksyms/types.c
index b1b82d166eb8..fa74e6fc26e3 100644
--- a/tools/gendwarfksyms/types.c
+++ b/tools/gendwarfksyms/types.c
@@ -166,8 +166,10 @@ static int process_fqn(struct state *state, struct cached_die *cache,
return 0; \
}
+DEFINE_PROCESS_UDATA_ATTRIBUTE(accessibility)
DEFINE_PROCESS_UDATA_ATTRIBUTE(alignment)
DEFINE_PROCESS_UDATA_ATTRIBUTE(byte_size)
+DEFINE_PROCESS_UDATA_ATTRIBUTE(data_member_location)
/* Match functions -- die_match_callback_t */
#define DEFINE_MATCH(type) \
@@ -176,8 +178,11 @@ DEFINE_PROCESS_UDATA_ATTRIBUTE(byte_size)
return dwarf_tag(die) == DW_TAG_##type##_type; \
}
+DEFINE_MATCH(enumerator)
DEFINE_MATCH(formal_parameter)
+DEFINE_MATCH(member)
DEFINE_MATCH(subrange)
+DEFINE_MATCH(variant)
bool match_all(Dwarf_Die *die)
{
@@ -222,6 +227,8 @@ static int __process_list_type(struct state *state, struct cached_die *cache,
{
check(process(state, cache, type));
check(process_type_attr(state, cache, die));
+ check(process_accessibility_attr(state, cache, die));
+ check(process_data_member_location_attr(state, cache, die));
check(process(state, cache, ","));
return check(process_linebreak(cache, 0));
}
@@ -234,6 +241,7 @@ static int __process_list_type(struct state *state, struct cached_die *cache,
}
DEFINE_PROCESS_LIST_TYPE(formal_parameter)
+DEFINE_PROCESS_LIST_TYPE(member)
/* Container types with DW_AT_type */
static int __process_type(struct state *state, struct cached_die *cache,
@@ -266,6 +274,7 @@ DEFINE_PROCESS_TYPE(reference)
DEFINE_PROCESS_TYPE(restrict)
DEFINE_PROCESS_TYPE(rvalue_reference)
DEFINE_PROCESS_TYPE(shared)
+DEFINE_PROCESS_TYPE(template_type_parameter)
DEFINE_PROCESS_TYPE(volatile)
DEFINE_PROCESS_TYPE(typedef)
@@ -318,6 +327,110 @@ static int process_subroutine_type(struct state *state,
return check(__process_subroutine_type(state, cache, die,
"subroutine_type"));
}
+
+static int process_variant_type(struct state *state, struct cached_die *cache,
+ Dwarf_Die *die)
+{
+ return check(process_die_container(state, cache, die, process_type,
+ match_member_type));
+}
+
+static int process_variant_part_type(struct state *state,
+ struct cached_die *cache, Dwarf_Die *die)
+{
+ check(process(state, cache, "variant_part {"));
+ check(process_linebreak(cache, 1));
+ check(process_die_container(state, cache, die, process_type,
+ match_variant_type));
+ check(process_linebreak(cache, -1));
+ check(process(state, cache, "},"));
+ return check(process_linebreak(cache, 0));
+}
+
+static int ___process_structure_type(struct state *state,
+ struct cached_die *cache, Dwarf_Die *die)
+{
+ switch (dwarf_tag(die)) {
+ case DW_TAG_member:
+ case DW_TAG_variant_part:
+ return check(process_type(state, cache, die));
+ case DW_TAG_class_type:
+ case DW_TAG_enumeration_type:
+ case DW_TAG_structure_type:
+ case DW_TAG_template_type_parameter:
+ case DW_TAG_union_type:
+ check(process_type(state, cache, die));
+ check(process(state, cache, ","));
+ return check(process_linebreak(cache, 0));
+ case DW_TAG_subprogram:
+ return 0; /* Skip member functions */
+ default:
+ error("unexpected structure_type child: %x", dwarf_tag(die));
+ return -1;
+ }
+}
+
+static int __process_structure_type(struct state *state,
+ struct cached_die *cache, Dwarf_Die *die,
+ const char *type,
+ die_callback_t process_func,
+ die_match_callback_t match_func)
+{
+ check(process(state, cache, type));
+ check(process_fqn(state, cache, die));
+ check(process(state, cache, " {"));
+ check(process_linebreak(cache, 1));
+
+ check(process_die_container(state, cache, die, process_func,
+ match_func));
+
+ check(process_linebreak(cache, -1));
+ check(process(state, cache, "}"));
+
+ check(process_byte_size_attr(state, cache, die));
+ check(process_alignment_attr(state, cache, die));
+
+ return 0;
+}
+
+#define DEFINE_PROCESS_STRUCTURE_TYPE(structure) \
+ static int process_##structure##_type( \
+ struct state *state, struct cached_die *cache, Dwarf_Die *die) \
+ { \
+ return check(__process_structure_type( \
+ state, cache, die, #structure "_type ", \
+ ___process_structure_type, match_all)); \
+ }
+
+DEFINE_PROCESS_STRUCTURE_TYPE(class)
+DEFINE_PROCESS_STRUCTURE_TYPE(structure)
+DEFINE_PROCESS_STRUCTURE_TYPE(union)
+
+static int process_enumerator_type(struct state *state,
+ struct cached_die *cache, Dwarf_Die *die)
+{
+ Dwarf_Word value;
+
+ check(process(state, cache, "enumerator "));
+ check(process_fqn(state, cache, die));
+
+ if (get_udata_attr(die, DW_AT_const_value, &value)) {
+ check(process(state, cache, " = "));
+ check(process_fmt(state, cache, "%" PRIu64, value));
+ }
+
+ check(process(state, cache, ","));
+ return check(process_linebreak(cache, 0));
+}
+
+static int process_enumeration_type(struct state *state,
+ struct cached_die *cache, Dwarf_Die *die)
+{
+ return check(__process_structure_type(state, cache, die,
+ "enumeration_type ", process_type,
+ match_enumerator_type));
+}
+
static int process_base_type(struct state *state, struct cached_die *cache,
Dwarf_Die *die)
{
@@ -402,17 +515,27 @@ static int process_type(struct state *state, struct cached_die *parent,
PROCESS_TYPE(rvalue_reference)
PROCESS_TYPE(shared)
PROCESS_TYPE(volatile)
+ /* Container types */
+ PROCESS_TYPE(class)
+ PROCESS_TYPE(structure)
+ PROCESS_TYPE(union)
+ PROCESS_TYPE(enumeration)
/* Subtypes */
+ PROCESS_TYPE(enumerator)
PROCESS_TYPE(formal_parameter)
+ PROCESS_TYPE(member)
PROCESS_TYPE(subrange)
+ PROCESS_TYPE(template_type_parameter)
+ PROCESS_TYPE(variant)
+ PROCESS_TYPE(variant_part)
/* Other types */
PROCESS_TYPE(array)
PROCESS_TYPE(base)
PROCESS_TYPE(subroutine)
PROCESS_TYPE(typedef)
default:
- debug("unimplemented type: %x", tag);
- break;
+ error("unexpected type: %x", tag);
+ return -1;
}
if (!no_cache) {
--
2.45.2.627.g7a2c4fd464-goog
next prev parent reply other threads:[~2024-06-17 17:58 UTC|newest]
Thread overview: 37+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-06-17 17:58 [PATCH 00/15] Implement MODVERSIONS for Rust Sami Tolvanen
2024-06-17 17:58 ` [PATCH 01/15] tools: Add gendwarfksyms Sami Tolvanen
2024-06-17 17:58 ` [PATCH 02/15] gendwarfksyms: Add symbol list input handling Sami Tolvanen
2024-06-17 17:58 ` [PATCH 03/15] gendwarfksyms: Add CRC calculation Sami Tolvanen
2024-06-17 17:58 ` [PATCH 04/15] gendwarfksyms: Expand base_type Sami Tolvanen
2024-06-17 17:58 ` [PATCH 05/15] gendwarfksyms: Add a cache Sami Tolvanen
2024-06-17 17:58 ` [PATCH 06/15] gendwarfksyms: Expand type modifiers and typedefs Sami Tolvanen
2024-06-17 17:58 ` [PATCH 07/15] gendwarfksyms: Add pretty-printing Sami Tolvanen
2024-06-17 17:58 ` [PATCH 08/15] gendwarfksyms: Expand subroutine_type Sami Tolvanen
2024-06-17 17:58 ` [PATCH 09/15] gendwarfksyms: Expand array_type Sami Tolvanen
2024-06-17 17:58 ` Sami Tolvanen [this message]
2024-06-17 17:58 ` [PATCH 11/15] gendwarfksyms: Limit structure expansion Sami Tolvanen
2024-06-17 17:58 ` [PATCH 12/15] gendwarfksyms: Add inline debugging Sami Tolvanen
2024-06-17 17:58 ` [PATCH 13/15] modpost: Add support for hashing long symbol names Sami Tolvanen
2024-06-18 16:47 ` Masahiro Yamada
2024-06-18 20:07 ` Sami Tolvanen
2024-06-17 17:58 ` [PATCH 14/15] module: Support hashed symbol names when checking modversions Sami Tolvanen
2024-06-17 17:58 ` [PATCH 15/15] kbuild: Use gendwarfksyms to generate Rust symbol versions Sami Tolvanen
2024-06-18 16:28 ` [PATCH 00/15] Implement MODVERSIONS for Rust Masahiro Yamada
2024-06-18 20:05 ` Sami Tolvanen
2024-06-18 16:44 ` Greg Kroah-Hartman
2024-06-18 16:50 ` Masahiro Yamada
2024-06-18 17:18 ` Greg Kroah-Hartman
2024-06-18 19:03 ` Masahiro Yamada
2024-06-18 20:19 ` Sami Tolvanen
2024-06-18 19:42 ` Luis Chamberlain
2024-06-18 21:19 ` Sami Tolvanen
2024-06-18 23:32 ` Luis Chamberlain
2024-07-10 7:30 ` Petr Pavlu
2024-07-15 20:39 ` Sami Tolvanen
2024-07-16 7:12 ` Greg Kroah-Hartman
2024-07-18 17:04 ` Sami Tolvanen
2024-07-22 8:20 ` Petr Pavlu
2024-07-26 21:05 ` Sami Tolvanen
2024-07-31 20:46 ` Neal Gompa
2024-08-01 11:22 ` Petr Pavlu
2024-08-01 19:38 ` Sami Tolvanen
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20240617175818.58219-27-samitolvanen@google.com \
--to=samitolvanen@google.com \
--cc=alex.gaynor@gmail.com \
--cc=gary@garyguo.net \
--cc=gregkh@linuxfoundation.org \
--cc=linux-kbuild@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-modules@vger.kernel.org \
--cc=masahiroy@kernel.org \
--cc=mcgrof@kernel.org \
--cc=mmaurer@google.com \
--cc=ojeda@kernel.org \
--cc=rust-for-linux@vger.kernel.org \
--cc=wedsonaf@gmail.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox