[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20240815173903.4172139-25-samitolvanen@google.com>
Date: Thu, 15 Aug 2024 17:39:08 +0000
From: Sami Tolvanen <samitolvanen@...gle.com>
To: Masahiro Yamada <masahiroy@...nel.org>, Luis Chamberlain <mcgrof@...nel.org>,
Miguel Ojeda <ojeda@...nel.org>, Greg Kroah-Hartman <gregkh@...uxfoundation.org>
Cc: Matthew Maurer <mmaurer@...gle.com>, Alex Gaynor <alex.gaynor@...il.com>,
Wedson Almeida Filho <wedsonaf@...il.com>, Gary Guo <gary@...yguo.net>, Petr Pavlu <petr.pavlu@...e.com>,
Neal Gompa <neal@...pa.dev>, Hector Martin <marcan@...can.st>, Janne Grunau <j@...nau.net>,
Asahi Linux <asahi@...ts.linux.dev>, linux-kbuild@...r.kernel.org,
linux-kernel@...r.kernel.org, linux-modules@...r.kernel.org,
rust-for-linux@...r.kernel.org, Sami Tolvanen <samitolvanen@...gle.com>
Subject: [PATCH v2 04/19] gendwarfksyms: Add support for type pointers
The compiler may choose not to emit type information in DWARF for
external symbols. Clang, for example, does this for symbols not
defined in the current TU.
To provide a way to work around this issue, add support for
__gendwarfksyms_ptr_<symbol> pointers that force the compiler to emit
the necessary type information in DWARF also for the missing symbols.
Example usage:
#define GENDWARFKSYMS_PTR(sym) \
static typeof(sym) *__gendwarfksyms_ptr_##sym __used \
__section(".discard.gendwarfksyms") = &sym;
extern int external_symbol(void);
GENDWARFKSYMS_PTR(external_symbol);
Signed-off-by: Sami Tolvanen <samitolvanen@...gle.com>
---
scripts/gendwarfksyms/dwarf.c | 26 +++++++++++++++++++++++++-
scripts/gendwarfksyms/gendwarfksyms.h | 6 ++++++
scripts/gendwarfksyms/symbols.c | 16 ++++++++++++++++
3 files changed, 47 insertions(+), 1 deletion(-)
diff --git a/scripts/gendwarfksyms/dwarf.c b/scripts/gendwarfksyms/dwarf.c
index 71cfab0553da..956b30224316 100644
--- a/scripts/gendwarfksyms/dwarf.c
+++ b/scripts/gendwarfksyms/dwarf.c
@@ -94,6 +94,28 @@ static int process_variable(struct state *state, Dwarf_Die *die)
return check(process(state, "variable;\n"));
}
+static int process_symbol_ptr(struct state *state, Dwarf_Die *die)
+{
+ Dwarf_Die ptr_type;
+ Dwarf_Die type;
+
+ if (!get_ref_die_attr(die, DW_AT_type, &ptr_type) ||
+ dwarf_tag(&ptr_type) != DW_TAG_pointer_type) {
+ error("%s must be a pointer type!", get_name(die));
+ return -1;
+ }
+
+ if (!get_ref_die_attr(&ptr_type, DW_AT_type, &type)) {
+ error("%s pointer missing a type attribute?", get_name(die));
+ return -1;
+ }
+
+ if (dwarf_tag(&type) == DW_TAG_subroutine_type)
+ return check(process_subprogram(state, &type));
+ else
+ return check(process_variable(state, &ptr_type));
+}
+
static int process_exported_symbols(struct state *state, Dwarf_Die *die)
{
int tag = dwarf_tag(die);
@@ -114,7 +136,9 @@ static int process_exported_symbols(struct state *state, Dwarf_Die *die)
debug("%s", state->sym->name);
- if (tag == DW_TAG_subprogram)
+ if (is_symbol_ptr(get_name(&state->die)))
+ check(process_symbol_ptr(state, &state->die));
+ else if (tag == DW_TAG_subprogram)
check(process_subprogram(state, &state->die));
else
check(process_variable(state, &state->die));
diff --git a/scripts/gendwarfksyms/gendwarfksyms.h b/scripts/gendwarfksyms/gendwarfksyms.h
index cb9106dfddb9..8f6acd1b8f8f 100644
--- a/scripts/gendwarfksyms/gendwarfksyms.h
+++ b/scripts/gendwarfksyms/gendwarfksyms.h
@@ -61,6 +61,11 @@ extern bool debug;
/*
* symbols.c
*/
+
+/* See symbols.c:is_symbol_ptr */
+#define SYMBOL_PTR_PREFIX "__gendwarfksyms_ptr_"
+#define SYMBOL_PTR_PREFIX_LEN (sizeof(SYMBOL_PTR_PREFIX) - 1)
+
struct symbol_addr {
uint32_t section;
Elf64_Addr address;
@@ -78,6 +83,7 @@ struct symbol {
struct hlist_node name_hash;
};
+extern bool is_symbol_ptr(const char *name);
extern int symbol_read_exports(FILE *file);
extern int symbol_read_symtab(int fd);
extern struct symbol *symbol_get(const char *name);
diff --git a/scripts/gendwarfksyms/symbols.c b/scripts/gendwarfksyms/symbols.c
index f96acb941196..d6d016458ae1 100644
--- a/scripts/gendwarfksyms/symbols.c
+++ b/scripts/gendwarfksyms/symbols.c
@@ -41,6 +41,20 @@ static int __for_each_addr(struct symbol *sym, symbol_callback_t func,
return processed;
}
+/*
+ * For symbols without debugging information (e.g. symbols defined in other
+ * TUs), we also match __gendwarfksyms_ptr_<symbol_name> symbols, which the
+ * kernel uses to ensure type information is present in the TU that exports
+ * the symbol. A __gendwarfksyms_ptr pointer must have the same type as the
+ * exported symbol, e.g.:
+ *
+ * typeof(symname) *__gendwarf_ptr_symname = &symname;
+ */
+bool is_symbol_ptr(const char *name)
+{
+ return name && !strncmp(name, SYMBOL_PTR_PREFIX, SYMBOL_PTR_PREFIX_LEN);
+}
+
static int for_each(const char *name, bool name_only, symbol_callback_t func,
void *data)
{
@@ -49,6 +63,8 @@ static int for_each(const char *name, bool name_only, symbol_callback_t func,
if (!name || !*name)
return 0;
+ if (is_symbol_ptr(name))
+ name += SYMBOL_PTR_PREFIX_LEN;
hash_for_each_possible_safe(symbol_names, match, tmp, name_hash,
name_hash(name)) {
--
2.46.0.184.g6999bdac58-goog
Powered by blists - more mailing lists