Re: [PATCH v3 03/20] tools: Add gendwarfksyms

2024-10-01 Thread Sami Tolvanen
Hi Petr,

On Tue, Oct 1, 2024 at 2:04 PM Petr Pavlu  wrote:
>
> On 9/23/24 20:18, Sami Tolvanen wrote:
> > + if (dwfl_getmodules(dwfl, &process_module, NULL, 0)) {
> > + error("dwfl_getmodules failed for '%s'", argv[n]);
> > + return -1;
> > + }
>
> Nit: The four error() calls don't need to be followed by 'return -1;'
> since the function now calls exit(1).

Good catch, I forgot to clean these up. I'll fix these.

> > + for_each(name, get_symbol, &sym);
> > + return sym;
> > +}
>
> Nit: The code inconsistently checks for a potential error from the
> function for_each(). Looking at the whole series, the value is checked
> using checkp() in functions symbol_set_crc(), symbol_set_ptr(),
> symbol_set_die(), is_exported(), but not in symbol_get() and
> elf_set_symbol_addr(). It would be good to unify this, or perhaps even
> make for_each() return an unsigned int to indicate it never fails?

True, there's no need to use check() anymore here. I'll change the
return value to unsigned int and clean up the error handling.

Sami



Re: [PATCH v3 03/20] tools: Add gendwarfksyms

2024-10-01 Thread Petr Pavlu
On 9/23/24 20:18, Sami Tolvanen wrote:
> Add a basic DWARF parser, which uses libdw to traverse the debugging
> information in an object file and looks for functions and variables.
> In follow-up patches, this will be expanded to produce symbol versions
> for CONFIG_MODVERSIONS from DWARF.
> 
> Signed-off-by: Sami Tolvanen 
> ---
>  kernel/module/Kconfig |   8 ++
>  scripts/Makefile  |   1 +
>  scripts/gendwarfksyms/.gitignore  |   2 +
>  scripts/gendwarfksyms/Makefile|   8 ++
>  scripts/gendwarfksyms/dwarf.c | 166 ++
>  scripts/gendwarfksyms/gendwarfksyms.c | 132 
>  scripts/gendwarfksyms/gendwarfksyms.h |  97 +++
>  scripts/gendwarfksyms/symbols.c   |  82 +
>  8 files changed, 496 insertions(+)
>  create mode 100644 scripts/gendwarfksyms/.gitignore
>  create mode 100644 scripts/gendwarfksyms/Makefile
>  create mode 100644 scripts/gendwarfksyms/dwarf.c
>  create mode 100644 scripts/gendwarfksyms/gendwarfksyms.c
>  create mode 100644 scripts/gendwarfksyms/gendwarfksyms.h
>  create mode 100644 scripts/gendwarfksyms/symbols.c
> 
> diff --git a/kernel/module/Kconfig b/kernel/module/Kconfig
> index ccdbd1bc12aa..c3a0172a909f 100644
> --- a/kernel/module/Kconfig
> +++ b/kernel/module/Kconfig
> @@ -168,6 +168,14 @@ config MODVERSIONS
> make them incompatible with the kernel you are running.  If
> unsure, say N.
>  
> +config GENDWARFKSYMS
> + bool
> + depends on DEBUG_INFO
> + # Requires full debugging information, split DWARF not supported.
> + depends on !DEBUG_INFO_REDUCED && !DEBUG_INFO_SPLIT
> + # Requires ELF object files.
> + depends on !LTO
> +
>  config ASM_MODVERSIONS
>   bool
>   default HAVE_ASM_MODVERSIONS && MODVERSIONS
> diff --git a/scripts/Makefile b/scripts/Makefile
> index 6bcda4b9d054..d7fec46d38c0 100644
> --- a/scripts/Makefile
> +++ b/scripts/Makefile
> @@ -54,6 +54,7 @@ targets += module.lds
>  
>  subdir-$(CONFIG_GCC_PLUGINS) += gcc-plugins
>  subdir-$(CONFIG_MODVERSIONS) += genksyms
> +subdir-$(CONFIG_GENDWARFKSYMS) += gendwarfksyms
>  subdir-$(CONFIG_SECURITY_SELINUX) += selinux
>  subdir-$(CONFIG_SECURITY_IPE) += ipe
>  
> diff --git a/scripts/gendwarfksyms/.gitignore 
> b/scripts/gendwarfksyms/.gitignore
> new file mode 100644
> index ..0927f8d3cd96
> --- /dev/null
> +++ b/scripts/gendwarfksyms/.gitignore
> @@ -0,0 +1,2 @@
> +# SPDX-License-Identifier: GPL-2.0
> +/gendwarfksyms
> diff --git a/scripts/gendwarfksyms/Makefile b/scripts/gendwarfksyms/Makefile
> new file mode 100644
> index ..9f8fec4fd39b
> --- /dev/null
> +++ b/scripts/gendwarfksyms/Makefile
> @@ -0,0 +1,8 @@
> +# SPDX-License-Identifier: GPL-2.0
> +hostprogs-always-y += gendwarfksyms
> +
> +gendwarfksyms-objs += gendwarfksyms.o
> +gendwarfksyms-objs += dwarf.o
> +gendwarfksyms-objs += symbols.o
> +
> +HOSTLDLIBS_gendwarfksyms := -ldw -lelf
> diff --git a/scripts/gendwarfksyms/dwarf.c b/scripts/gendwarfksyms/dwarf.c
> new file mode 100644
> index ..81df3e2ad3ae
> --- /dev/null
> +++ b/scripts/gendwarfksyms/dwarf.c
> @@ -0,0 +1,166 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Copyright (C) 2024 Google LLC
> + */
> +
> +#include "gendwarfksyms.h"
> +
> +static bool get_ref_die_attr(Dwarf_Die *die, unsigned int id, Dwarf_Die 
> *value)
> +{
> + Dwarf_Attribute da;
> +
> + /* dwarf_formref_die returns a pointer instead of an error value. */
> + return dwarf_attr(die, id, &da) && dwarf_formref_die(&da, value);
> +}
> +
> +#define DEFINE_GET_STRING_ATTR(attr) \
> + static const char *get_##attr##_attr(Dwarf_Die *die) \
> + {\
> + Dwarf_Attribute da;  \
> + if (dwarf_attr(die, DW_AT_##attr, &da))  \
> + return dwarf_formstring(&da);\
> + return NULL; \
> + }
> +
> +DEFINE_GET_STRING_ATTR(name)
> +DEFINE_GET_STRING_ATTR(linkage_name)
> +
> +static const char *get_symbol_name(Dwarf_Die *die)
> +{
> + const char *name;
> +
> + /* rustc uses DW_AT_linkage_name for exported symbols */
> + name = get_linkage_name_attr(die);
> + if (!name)
> + name = get_name_attr(die);
> +
> + return name;
> +}
> +
> +static bool match_export_symbol(struct state *state, Dwarf_Die *die)
> +{
> + Dwarf_Die *source = die;
> + Dwarf_Die origin;
> +
> + /* If the DIE has an abstract origin, use it for type information. */
> + if (get_ref_die_attr(die, DW_AT_abstract_origin, &origin))
> + source = &origin;
> +
> + state->sym = symbol_get(get_symbol_name(die));
> +
> + /* Look up using the origin name if there are no matches. */
> + if (!state->sym && source != die)
> + state->sym = symbol_get(get_symbol_name(source));
> +
> + state->

[PATCH v3 03/20] tools: Add gendwarfksyms

2024-09-23 Thread Sami Tolvanen
Add a basic DWARF parser, which uses libdw to traverse the debugging
information in an object file and looks for functions and variables.
In follow-up patches, this will be expanded to produce symbol versions
for CONFIG_MODVERSIONS from DWARF.

Signed-off-by: Sami Tolvanen 
---
 kernel/module/Kconfig |   8 ++
 scripts/Makefile  |   1 +
 scripts/gendwarfksyms/.gitignore  |   2 +
 scripts/gendwarfksyms/Makefile|   8 ++
 scripts/gendwarfksyms/dwarf.c | 166 ++
 scripts/gendwarfksyms/gendwarfksyms.c | 132 
 scripts/gendwarfksyms/gendwarfksyms.h |  97 +++
 scripts/gendwarfksyms/symbols.c   |  82 +
 8 files changed, 496 insertions(+)
 create mode 100644 scripts/gendwarfksyms/.gitignore
 create mode 100644 scripts/gendwarfksyms/Makefile
 create mode 100644 scripts/gendwarfksyms/dwarf.c
 create mode 100644 scripts/gendwarfksyms/gendwarfksyms.c
 create mode 100644 scripts/gendwarfksyms/gendwarfksyms.h
 create mode 100644 scripts/gendwarfksyms/symbols.c

diff --git a/kernel/module/Kconfig b/kernel/module/Kconfig
index ccdbd1bc12aa..c3a0172a909f 100644
--- a/kernel/module/Kconfig
+++ b/kernel/module/Kconfig
@@ -168,6 +168,14 @@ config MODVERSIONS
  make them incompatible with the kernel you are running.  If
  unsure, say N.
 
+config GENDWARFKSYMS
+   bool
+   depends on DEBUG_INFO
+   # Requires full debugging information, split DWARF not supported.
+   depends on !DEBUG_INFO_REDUCED && !DEBUG_INFO_SPLIT
+   # Requires ELF object files.
+   depends on !LTO
+
 config ASM_MODVERSIONS
bool
default HAVE_ASM_MODVERSIONS && MODVERSIONS
diff --git a/scripts/Makefile b/scripts/Makefile
index 6bcda4b9d054..d7fec46d38c0 100644
--- a/scripts/Makefile
+++ b/scripts/Makefile
@@ -54,6 +54,7 @@ targets += module.lds
 
 subdir-$(CONFIG_GCC_PLUGINS) += gcc-plugins
 subdir-$(CONFIG_MODVERSIONS) += genksyms
+subdir-$(CONFIG_GENDWARFKSYMS) += gendwarfksyms
 subdir-$(CONFIG_SECURITY_SELINUX) += selinux
 subdir-$(CONFIG_SECURITY_IPE) += ipe
 
diff --git a/scripts/gendwarfksyms/.gitignore b/scripts/gendwarfksyms/.gitignore
new file mode 100644
index ..0927f8d3cd96
--- /dev/null
+++ b/scripts/gendwarfksyms/.gitignore
@@ -0,0 +1,2 @@
+# SPDX-License-Identifier: GPL-2.0
+/gendwarfksyms
diff --git a/scripts/gendwarfksyms/Makefile b/scripts/gendwarfksyms/Makefile
new file mode 100644
index ..9f8fec4fd39b
--- /dev/null
+++ b/scripts/gendwarfksyms/Makefile
@@ -0,0 +1,8 @@
+# SPDX-License-Identifier: GPL-2.0
+hostprogs-always-y += gendwarfksyms
+
+gendwarfksyms-objs += gendwarfksyms.o
+gendwarfksyms-objs += dwarf.o
+gendwarfksyms-objs += symbols.o
+
+HOSTLDLIBS_gendwarfksyms := -ldw -lelf
diff --git a/scripts/gendwarfksyms/dwarf.c b/scripts/gendwarfksyms/dwarf.c
new file mode 100644
index ..81df3e2ad3ae
--- /dev/null
+++ b/scripts/gendwarfksyms/dwarf.c
@@ -0,0 +1,166 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2024 Google LLC
+ */
+
+#include "gendwarfksyms.h"
+
+static bool get_ref_die_attr(Dwarf_Die *die, unsigned int id, Dwarf_Die *value)
+{
+   Dwarf_Attribute da;
+
+   /* dwarf_formref_die returns a pointer instead of an error value. */
+   return dwarf_attr(die, id, &da) && dwarf_formref_die(&da, value);
+}
+
+#define DEFINE_GET_STRING_ATTR(attr) \
+   static const char *get_##attr##_attr(Dwarf_Die *die) \
+   {\
+   Dwarf_Attribute da;  \
+   if (dwarf_attr(die, DW_AT_##attr, &da))  \
+   return dwarf_formstring(&da);\
+   return NULL; \
+   }
+
+DEFINE_GET_STRING_ATTR(name)
+DEFINE_GET_STRING_ATTR(linkage_name)
+
+static const char *get_symbol_name(Dwarf_Die *die)
+{
+   const char *name;
+
+   /* rustc uses DW_AT_linkage_name for exported symbols */
+   name = get_linkage_name_attr(die);
+   if (!name)
+   name = get_name_attr(die);
+
+   return name;
+}
+
+static bool match_export_symbol(struct state *state, Dwarf_Die *die)
+{
+   Dwarf_Die *source = die;
+   Dwarf_Die origin;
+
+   /* If the DIE has an abstract origin, use it for type information. */
+   if (get_ref_die_attr(die, DW_AT_abstract_origin, &origin))
+   source = &origin;
+
+   state->sym = symbol_get(get_symbol_name(die));
+
+   /* Look up using the origin name if there are no matches. */
+   if (!state->sym && source != die)
+   state->sym = symbol_get(get_symbol_name(source));
+
+   state->die = *source;
+   return !!state->sym;
+}
+
+/*
+ * Type string processing
+ */
+static void process(const char *s)
+{
+   s = s ?: "";
+
+   if (dump_dies)
+   fputs(s, stderr);
+}
+
+bool match_all(Dwarf_Die *die)
+{
+