From: Arnaldo Carvalho de Melo <acme@kernel.org>
To: Douglas RAILLARD <douglas.raillard@arm.com>
Cc: acme@redhat.com, dwarves@vger.kernel.org
Subject: Re: [PATCH 1/2] fprintf: Fix nested struct printing
Date: Fri, 15 Oct 2021 10:08:25 -0300 [thread overview]
Message-ID: <YWl9SQG9qwm3Sz6U@kernel.org> (raw)
In-Reply-To: <20211014114850.310575-1-douglas.raillard@arm.com>
Em Thu, Oct 14, 2021 at 12:48:49PM +0100, Douglas RAILLARD escreveu:
> From: Douglas Raillard <douglas.raillard@arm.com>
>
> This code:
>
> struct X {
> struct {
> } __attribute__((foo)) x __attribute__((bar));
> }
>
> Was wrongly printed as:
>
> struct X {
> struct {
> } x __attribute__((foo)) __attribute__((bar));
> }
>
> This unfortunately matters a lot, since "bar" is suppose to apply to
> "x", but "foo" to typeof(x). In the wrong form, both apply to "x",
> leading to e.g. incorrect layout for __aligned__ attribute.
I couldn't quickly find a change in behaviour with a random vmlinux I
have for testing:
⬢[acme@toolbox pahole]$ build/pahole.old -F dwarf vmlinux > before
⬢[acme@toolbox pahole]$ build/pahole -F dwarf vmlinux > after
⬢[acme@toolbox pahole]$ diff -u before after
⬢[acme@toolbox pahole]$ grep "__attribute__.*__attribute__" before | wc -l
40
⬢[acme@toolbox pahole]$
btdiff is happy tho:
⬢[acme@toolbox pahole]$ btfdiff vmlinux
⬢[acme@toolbox pahole]$ cat btfdiff
#!/bin/bash
# SPDX-License-Identifier: GPL-2.0-only
# Copyright © 2019 Red Hat Inc, Arnaldo Carvalho de Melo <acme@redhat.com>
# Use pahole to produce output from BTF and from DWARF, then do a diff
# Use --flat_arrays with DWARF as BTF, like CTF, flattens arrays.
# Use --show_private_classes as BTF shows all structs, while pahole knows
# if some struct is defined only inside another struct/class or in a function,
# this information is not available when loading from BTF.
if [ $# -eq 0 ] ; then
echo "Usage: btfdiff <filename_with_DWARF_and_maybe_BTF_info> [<filename_with_BTF_info>]"
exit 1
fi
dwarf_input=$1
btf_input=$dwarf_input
if [ $# -eq 2 ] ; then
btf_input=$2
fi
btf_output=$(mktemp /tmp/btfdiff.btf.XXXXXX)
dwarf_output=$(mktemp /tmp/btfdiff.dwarf.XXXXXX)
pahole_bin=${PAHOLE-"pahole"}
${pahole_bin} -F dwarf \
--flat_arrays \
--sort \
--jobs \
--suppress_aligned_attribute \
--suppress_force_paddings \
--suppress_packed \
--show_private_classes $dwarf_input > $dwarf_output
${pahole_bin} -F btf \
--sort \
--suppress_packed \
$btf_input > $btf_output
diff -up $dwarf_output $btf_output
rm -f $btf_output $dwarf_output
exit 0
⬢[acme@toolbox pahole]$
As is fullcircle:
⬢[acme@toolbox pahole]$ fullcircle tcp.o
⬢[acme@toolbox pahole]$ cat fullcircle
#!/bin/bash
# SPDX-License-Identifier: GPL-2.0-only
# Copyright © 2019 Red Hat Inc, Arnaldo Carvalho de Melo <acme@redhat.com>
# Use pfunct to produce compilable output from a object, then do a codiff -s
# To see if the type information generated from source code generated
# from type information in a file compiled from the original source code matches.
if [ $# -eq 0 ] ; then
echo "Usage: fullcircle <filename_with_type_info>"
exit 1
fi
file=$1
nr_cus=$(readelf -wi ${file} | grep DW_TAG_compile_unit | wc -l)
if [ $nr_cus -gt 1 ]; then
exit 0
fi
c_output=$(mktemp /tmp/fullcircle.XXXXXX.c)
o_output=$(mktemp /tmp/fullcircle.XXXXXX.o)
pfunct_bin=${PFUNCT-"pfunct"}
codiff_bin=${CODIFF-"codiff"}
# See how your DW_AT_producer looks like and find the
# right regexp to get after the GCC version string, this one
# seems good enough for Red Hat/Fedora/CentOS that look like:
#
# DW_AT_producer : (indirect string, offset: 0x3583): GNU C89 8.2.1 20181215 (Red Hat 8.2.1-6) -mno-sse -mno-mmx
#
# So we need from -mno-sse onwards
CFLAGS=$(readelf -wi $file | grep -w DW_AT_producer | sed -r 's/.*\)( -[[:alnum:]]+.*)+/\1/g')
# Check if we managed to do the sed or if this is something like GNU AS
[ "${CFLAGS/DW_AT_producer/}" != "${CFLAGS}" ] && exit
${pfunct_bin} --compile $file > $c_output
gcc $CFLAGS -c -g $c_output -o $o_output
${codiff_bin} -q -s $file $o_output
rm -f $c_output $o_output
exit 0
⬢[acme@toolbox pahole]$
- Arnaldo
> Signed-off-by: Douglas Raillard <douglas.raillard@arm.com>
> ---
> dwarves_fprintf.c | 22 ++++++++++++++++++----
> 1 file changed, 18 insertions(+), 4 deletions(-)
>
> diff --git a/dwarves_fprintf.c b/dwarves_fprintf.c
> index c35868a..1c1d949 100644
> --- a/dwarves_fprintf.c
> +++ b/dwarves_fprintf.c
> @@ -787,7 +787,7 @@ print_default:
> (type->tag == DW_TAG_class_type &&
> !tconf.classes_as_structs) ? "class" : "struct",
> tconf.type_spacing - 7,
> - type__name(ctype), name);
> + type__name(ctype), name ?: "");
> } else {
> struct class *cclass = tag__class(type);
>
> @@ -802,7 +802,7 @@ print_default:
> ctype = tag__type(type);
>
> if (type__name(ctype) != NULL && !expand_types) {
> - printed += fprintf(fp, "union %-*s %s", tconf.type_spacing - 6, type__name(ctype), name);
> + printed += fprintf(fp, "union %-*s %s", tconf.type_spacing - 6, type__name(ctype), name ?: "");
> } else {
> tconf.type_spacing -= 8;
> printed += union__fprintf(ctype, cu, &tconf, fp);
> @@ -812,7 +812,7 @@ print_default:
> ctype = tag__type(type);
>
> if (type__name(ctype) != NULL)
> - printed += fprintf(fp, "enum %-*s %s", tconf.type_spacing - 5, type__name(ctype), name);
> + printed += fprintf(fp, "enum %-*s %s", tconf.type_spacing - 5, type__name(ctype), name ?: "");
> else
> printed += enumeration__fprintf(type, &tconf, fp);
> break;
> @@ -863,7 +863,21 @@ static size_t class_member__fprintf(struct class_member *member, bool union_memb
> if (member->is_static)
> printed += fprintf(fp, "static ");
>
> - printed += type__fprintf(type, cu, name, &sconf, fp);
> + /* For struct-like constructs, the name of the member cannot be
> + * conflated with the name of its type, otherwise __attribute__ are
> + * printed in the wrong order.
> + */
> + if (tag__is_union(type) || tag__is_struct(type) ||
> + tag__is_enumeration(type)) {
> + printed += type__fprintf(type, cu, NULL, &sconf, fp);
> + if (name) {
> + if (!type__name(tag__type(type)))
> + printed += fprintf(fp, " ");
> + printed += fprintf(fp, "%s", name);
> + }
> + } else {
> + printed += type__fprintf(type, cu, name, &sconf, fp);
> + }
>
> if (member->is_static) {
> if (member->const_value != 0)
> --
> 2.25.1
--
- Arnaldo
next prev parent reply other threads:[~2021-10-15 13:08 UTC|newest]
Thread overview: 6+ messages / expand[flat|nested] mbox.gz Atom feed top
2021-10-14 11:48 [PATCH 1/2] fprintf: Fix nested struct printing Douglas RAILLARD
2021-10-14 11:48 ` [PATCH 2/2] btf_loader.c: Infer alignment info Douglas RAILLARD
2021-10-15 13:12 ` Arnaldo Carvalho de Melo
2021-10-18 10:40 ` Douglas Raillard
2021-10-15 13:08 ` Arnaldo Carvalho de Melo [this message]
2021-10-18 10:34 ` [PATCH 1/2] fprintf: Fix nested struct printing Douglas Raillard
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=YWl9SQG9qwm3Sz6U@kernel.org \
--to=acme@kernel.org \
--cc=acme@redhat.com \
--cc=douglas.raillard@arm.com \
--cc=dwarves@vger.kernel.org \
/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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.