Re: pahole issues with Rust DWARF was: Re: [PATCH 1/1] pahole/Rust: Check that we're adding DW_TAG_member sorted by byte offset

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Em Mon, Feb 13, 2023 at 01:45:02PM +0100, Miguel Ojeda escreveu:
> On Mon, Feb 13, 2023 at 1:09 PM Arnaldo Carvalho de Melo <arnaldo.melo@xxxxxxxxx> wrote:
> > The namespace.o seems to be ok:
 
> I saw the other message too -- this looks great, thanks a ton.
 
> > The core one needs work:
 
> If `core.o` works, then I think it is likely other things will work :)
 
> I can try to extract the cases for those into simpler `.o` files, if
> you would find simpler test cases useful (perhaps for the test suite
> etc.).

That would be great!

I tried starting this path with this, spitted out by ChatGPT (minus the
'pub' in from of main):

⬢[acme@toolbox pahole-rust-cases]$ cat template_type.rs
// Provided by ChatGPT

use std::ops::Add;

// Define a generic struct template with a single type parameter `T`.
struct Point<T> {
    x: T,
    y: T,
}

// Implement a method for the `Point` struct that adds two points together.
// The method uses the `Add` trait to ensure that the type `T` supports addition.
impl<T: Add<Output=T>> Point<T> {
    fn add_points(self, other: Point<T>) -> Point<T> {
        Point {
            x: self.x + other.x,
            y: self.y + other.y,
        }
    }
}

pub fn main() {
    // Create two `Point` instances, using `i32` as the type parameter.
    let p1 = Point { x: 1, y: 2 };
    let p2 = Point { x: 3, y: 4 };

    // Add the two points together using the `add_points` method.
    let p3 = p1.add_points(p2);

    // Print the result.
    println!("Point: ({}, {})", p3.x, p3.y);
}
⬢[acme@toolbox pahole-rust-cases]$

And then handle the DW_TAG_template_type_parameter for a
DW_TAG_subroutine:

 <3><12d>: Abbrev Number: 5 (DW_TAG_structure_type)
    <12e>   DW_AT_name        : (indirect string, offset: 0x299): ArgumentV1
    <132>   DW_AT_byte_size   : 16
    <133>   DW_AT_alignment   : 8
 <4><134>: Abbrev Number: 6 (DW_TAG_member)
    <135>   DW_AT_name        : (indirect string, offset: 0xd7): value
    <139>   DW_AT_type        : <0x43a>
    <13d>   DW_AT_alignment   : 8
    <13e>   DW_AT_data_member_location: 0
 <4><13f>: Abbrev Number: 6 (DW_TAG_member)
    <140>   DW_AT_name        : (indirect string, offset: 0x10e): formatter
    <144>   DW_AT_type        : <0x447>
    <148>   DW_AT_alignment   : 8
    <149>   DW_AT_data_member_location: 8
 <4><14a>: Abbrev Number: 11 (DW_TAG_subprogram)
    <14b>   DW_AT_linkage_name: (indirect string, offset: 0x2a8): _ZN4core3fmt10ArgumentV13new17h167b8c43a2ee7614E
    <14f>   DW_AT_name        : (indirect string, offset: 0x2d9): new<i32>
    <153>   DW_AT_decl_file   : 2
    <154>   DW_AT_decl_line   : 333
    <156>   DW_AT_type        : <0x12d>
    <15a>   DW_AT_inline      : 1       (inlined)
 <5><15b>: Abbrev Number: 12 (DW_TAG_template_type_param)
    <15c>   DW_AT_type        : <0x4e3>
    <160>   DW_AT_name        : (indirect string, offset: 0x125): T
 <5><164>: Abbrev Number: 13 (DW_TAG_variable)

I'll have to stop now, but was at the point of changing ftype__fprintf()
somehow to show that template type parameter, with the patch at the end
of this message I get this:

⬢[acme@toolbox pahole]$ pahole --show_private_classes ../pahole-rust-cases/template_type.o
die__process_class: tag not supported 0x33 (variant_part)!
die__process_class: tag not supported 0x2f (template_type_parameter)!
struct Argument {
	usize                      position __attribute__((__aligned__(8))); /*     0     8 */
	struct FormatSpec          format __attribute__((__aligned__(8))); /*     8    48 */

	/* XXX last struct has 7 bytes of padding */

	/* size: 56, cachelines: 1, members: 2 */
	/* paddings: 1, sum paddings: 7 */
	/* forced alignments: 2 */
	/* last cacheline: 56 bytes */
} __attribute__((__aligned__(8)));
struct FormatSpec {
	struct Count               precision __attribute__((__aligned__(8))); /*     0    16 */

	/* XXX last struct has 16 bytes of padding */

	struct Count               width __attribute__((__aligned__(8))); /*    16    16 */

	/* XXX last struct has 16 bytes of padding */

	char                       fill __attribute__((__aligned__(4))); /*    32     4 */
	u32                        flags __attribute__((__aligned__(4))); /*    36     4 */
	enum Alignment             align __attribute__((__aligned__(1))); /*    40     1 */

	/* size: 48, cachelines: 1, members: 5 */
	/* padding: 7 */
	/* paddings: 2, sum paddings: 32 */
	/* forced alignments: 5 */
	/* last cacheline: 48 bytes */
} __attribute__((__aligned__(8)));
struct Is {

	/* XXX 8 bytes hole, try to pack */

	usize                      __0 __attribute__((__aligned__(8))); /*     8     8 */

	/* size: 16, cachelines: 1, members: 1 */
	/* sum members: 8, holes: 1, sum holes: 8 */
	/* forced alignments: 1, forced holes: 1, sum forced holes: 8 */
	/* last cacheline: 16 bytes */
} __attribute__((__aligned__(8)));
struct Param {

	/* XXX 8 bytes hole, try to pack */

	usize                      __0 __attribute__((__aligned__(8))); /*     8     8 */

	/* size: 16, cachelines: 1, members: 1 */
	/* sum members: 8, holes: 1, sum holes: 8 */
	/* forced alignments: 1, forced holes: 1, sum forced holes: 8 */
	/* last cacheline: 16 bytes */
} __attribute__((__aligned__(8)));
struct Implied {

	/* size: 16, cachelines: 1, members: 0 */
	/* padding: 16 */
	/* last cacheline: 16 bytes */
} __attribute__((__aligned__(8)));
struct Count {

	/* size: 16, cachelines: 1, members: 0 */
	/* padding: 16 */
	/* last cacheline: 16 bytes */
} __attribute__((__aligned__(8)));
struct ArgumentV1 {
	struct Opaque *            value __attribute__((__aligned__(8))); /*     0     8 */
	struct Result<(), core::fmt::Error> (*formatter)(struct Opaque *, struct Formatter *) __attribute__((__aligned__(8))); /*     8     8 */

	/* size: 16, cachelines: 1, members: 2 */
	/* forced alignments: 2 */
	/* last cacheline: 16 bytes */
} __attribute__((__aligned__(8)));
struct Opaque {

	/* size: 0, cachelines: 0, members: 0 */
} __attribute__((__aligned__(1)));
struct Error {

	/* size: 0, cachelines: 0, members: 0 */
} __attribute__((__aligned__(1)));
struct Formatter {
	struct Option<usize>       width __attribute__((__aligned__(8))); /*     0    16 */

	/* XXX last struct has 16 bytes of padding */

	struct Option<usize>       precision __attribute__((__aligned__(8))); /*    16    16 */

	/* XXX last struct has 16 bytes of padding */

	struct &mut dyn core::fmt::Write buf __attribute__((__aligned__(8))); /*    32    16 */
	u32                        flags __attribute__((__aligned__(4))); /*    48     4 */
	char                       fill __attribute__((__aligned__(4))); /*    52     4 */
	enum Alignment             align __attribute__((__aligned__(1))); /*    56     1 */

	/* size: 64, cachelines: 1, members: 6 */
	/* padding: 7 */
	/* paddings: 2, sum paddings: 32 */
	/* forced alignments: 6 */
} __attribute__((__aligned__(8)));
struct Arguments {
	struct &[&str]             pieces __attribute__((__aligned__(8))); /*     0    16 */
	struct Option<&[core::fmt::rt::v1::Argument]> fmt __attribute__((__aligned__(8))); /*    16    16 */

	/* XXX last struct has 16 bytes of padding */

	struct &[core::fmt::ArgumentV1] args __attribute__((__aligned__(8))); /*    32    16 */

	/* size: 48, cachelines: 1, members: 3 */
	/* paddings: 1, sum paddings: 16 */
	/* forced alignments: 3 */
	/* last cacheline: 48 bytes */
} __attribute__((__aligned__(8)));
struct Ok {

	/* XXX 1 byte hole, try to pack */

	()                         __0 __attribute__((__aligned__(1))); /*     1     0 */

	/* size: 1, cachelines: 1, members: 1 */
	/* forced alignments: 1, forced holes: 1, sum forced holes: 1 */
	/* last cacheline: 1 bytes */
} __attribute__((__aligned__(1)));
struct Err {

	/* XXX 1 byte hole, try to pack */

	struct Error               __0 __attribute__((__aligned__(1))); /*     1     0 */

	/* size: 1, cachelines: 1, members: 1 */
	/* forced alignments: 1, forced holes: 1, sum forced holes: 1 */
	/* last cacheline: 1 bytes */
} __attribute__((__aligned__(1)));
struct Result<(), core::fmt::Error> {

	/* size: 1, cachelines: 0, members: 0 */
	/* padding: 1 */
	/* last cacheline: 1 bytes */
} __attribute__((__aligned__(1)));
struct None {

	/* size: 16, cachelines: 1, members: 0 */
	/* padding: 16 */
	/* last cacheline: 16 bytes */
} __attribute__((__aligned__(8)));
struct Some {

	/* XXX 8 bytes hole, try to pack */

	usize                      __0 __attribute__((__aligned__(8))); /*     8     8 */

	/* size: 16, cachelines: 1, members: 1 */
	/* sum members: 8, holes: 1, sum holes: 8 */
	/* forced alignments: 1, forced holes: 1, sum forced holes: 8 */
	/* last cacheline: 16 bytes */
} __attribute__((__aligned__(8)));
struct Option<usize> {

	/* size: 16, cachelines: 1, members: 0 */
	/* padding: 16 */
	/* last cacheline: 16 bytes */
} __attribute__((__aligned__(8)));
struct Some {
	struct &[core::fmt::rt::v1::Argument] __0 __attribute__((__aligned__(8))); /*     0    16 */

	/* size: 16, cachelines: 1, members: 1 */
	/* forced alignments: 1 */
	/* last cacheline: 16 bytes */
} __attribute__((__aligned__(8)));
struct Option<&[core::fmt::rt::v1::Argument]> {

	/* size: 16, cachelines: 1, members: 0 */
	/* padding: 16 */
	/* last cacheline: 16 bytes */
} __attribute__((__aligned__(8)));
struct &mut dyn core::fmt::Write {
	struct dyn core::fmt::Write * pointer __attribute__((__aligned__(8))); /*     0     8 */
	usize *                    vtable __attribute__((__aligned__(8))); /*     8     8 */

	/* size: 16, cachelines: 1, members: 2 */
	/* forced alignments: 2 */
	/* last cacheline: 16 bytes */
} __attribute__((__aligned__(8)));
struct dyn core::fmt::Write {

	/* size: 0, cachelines: 0, members: 0 */
} __attribute__((__aligned__(1)));
struct &[&str] {
	struct &str *              data_ptr __attribute__((__aligned__(8))); /*     0     8 */
	usize                      length __attribute__((__aligned__(8))); /*     8     8 */

	/* size: 16, cachelines: 1, members: 2 */
	/* forced alignments: 2 */
	/* last cacheline: 16 bytes */
} __attribute__((__aligned__(8)));
struct &str {
	u8 *                       data_ptr __attribute__((__aligned__(8))); /*     0     8 */
	usize                      length __attribute__((__aligned__(8))); /*     8     8 */

	/* size: 16, cachelines: 1, members: 2 */
	/* forced alignments: 2 */
	/* last cacheline: 16 bytes */
} __attribute__((__aligned__(8)));
struct &[core::fmt::rt::v1::Argument] {
	struct Argument *          data_ptr __attribute__((__aligned__(8))); /*     0     8 */
	usize                      length __attribute__((__aligned__(8))); /*     8     8 */

	/* size: 16, cachelines: 1, members: 2 */
	/* forced alignments: 2 */
	/* last cacheline: 16 bytes */
} __attribute__((__aligned__(8)));
struct &[core::fmt::ArgumentV1] {
	struct ArgumentV1 *        data_ptr __attribute__((__aligned__(8))); /*     0     8 */
	usize                      length __attribute__((__aligned__(8))); /*     8     8 */

	/* size: 16, cachelines: 1, members: 2 */
	/* forced alignments: 2 */
	/* last cacheline: 16 bytes */
} __attribute__((__aligned__(8)));
struct Point<i32> {
	i32                        x __attribute__((__aligned__(4))); /*     0     4 */
	i32                        y __attribute__((__aligned__(4))); /*     4     4 */

	/* size: 8, cachelines: 1, members: 2 */
	/* forced alignments: 2 */
	/* last cacheline: 8 bytes */
} __attribute__((__aligned__(4)));
⬢[acme@toolbox pahole]$

I'll cut version 1.25 with what is in the 'master' and 'next' now as
binutils 2.40 is out and emitting DW_TAG_unspecified_type, that isn't
supported by pahole 1.24 and also Alan's work on optimized functions,
etc.

- Arnaldo

diff --git a/dwarf_loader.c b/dwarf_loader.c
index a77598dc3affca88..b767bcaa9322c95a 100644
--- a/dwarf_loader.c
+++ b/dwarf_loader.c
@@ -1093,6 +1093,18 @@ static struct parameter *parameter__new(Dwarf_Die *die, struct cu *cu,
 	return parm;
 }
 
+static struct template_type_parameter *template_type_parameter__new(Dwarf_Die *die, struct cu *cu, struct conf_load *conf)
+{
+	struct template_type_parameter *parm = tag__alloc(cu, sizeof(*parm));
+
+	if (parm != NULL) {
+		tag__init(&parm->tag, cu, die);
+		parm->name = attr_string(die, DW_AT_name, conf);
+	}
+
+	return parm;
+}
+
 static struct inline_expansion *inline_expansion__new(Dwarf_Die *die, struct cu *cu, struct conf_load *conf)
 {
 	struct inline_expansion *exp = tag__alloc(cu, sizeof(*exp));
@@ -1211,6 +1223,7 @@ static void ftype__init(struct ftype *ftype, Dwarf_Die *die, struct cu *cu)
 #endif
 	tag__init(&ftype->tag, cu, die);
 	INIT_LIST_HEAD(&ftype->parms);
+	INIT_LIST_HEAD(&ftype->template_type_parms);
 	ftype->nr_parms	    = 0;
 	ftype->unspec_parms = 0;
 }
@@ -1566,6 +1579,19 @@ static struct tag *die__create_new_parameter(Dwarf_Die *die,
 	return &parm->tag;
 }
 
+static struct tag *die__create_new_template_type_parameter(Dwarf_Die *die, struct ftype *ftype,
+							   struct cu *cu, struct conf_load *conf)
+{
+	struct template_type_parameter *parm = template_type_parameter__new(die, cu, conf);
+
+	if (parm == NULL)
+		return NULL;
+
+	ftype__add_template_type_parameter(ftype, parm);
+
+	return &parm->tag;
+}
+
 static struct tag *die__create_new_label(Dwarf_Die *die,
 					 struct lexblock *lexblock,
 					 struct cu *cu, struct conf_load *conf)
@@ -1989,6 +2015,8 @@ static int die__process_function(Dwarf_Die *die, struct ftype *ftype,
 		case DW_TAG_GNU_template_template_param:
 #endif
 		case DW_TAG_template_type_parameter:
+			tag = die__create_new_template_type_parameter(die, ftype, cu, conf);
+			break;
 		case DW_TAG_template_value_parameter:
 			/* FIXME: probably we'll have to attach this as a list of
  			 * template parameters to use at class__fprintf time... 
diff --git a/dwarves.c b/dwarves.c
index b43031c93c5cab58..6a8feccc2d45c60d 100644
--- a/dwarves.c
+++ b/dwarves.c
@@ -1391,6 +1391,12 @@ void ftype__add_parameter(struct ftype *ftype, struct parameter *parm)
 	list_add_tail(&parm->tag.node, &ftype->parms);
 }
 
+void ftype__add_template_type_parameter(struct ftype *ftype, struct template_type_parameter *parm)
+{
+	++ftype->nr_template_type_parms;
+	list_add_tail(&parm->tag.node, &ftype->template_type_parms);
+}
+
 void lexblock__add_tag(struct lexblock *block, struct tag *tag)
 {
 	list_add_tail(&tag->node, &block->tags);
diff --git a/dwarves.h b/dwarves.h
index 24a1909a60389dee..5c9952bfddaed301 100644
--- a/dwarves.h
+++ b/dwarves.h
@@ -825,13 +825,30 @@ static inline const char *parameter__name(const struct parameter *parm)
 	return parm->name;
 }
 
+struct template_type_parameter {
+	struct tag tag;
+	const char *name;
+};
+
+static inline struct template_type_parameter *tag__template_type_parameter(const struct tag *tag)
+{
+	return (struct template_type_parameter *)tag;
+}
+
+static inline const char *template_type_parameter__name(const struct template_type_parameter *parm)
+{
+	return parm->name;
+}
+
 /*
  * tag.tag can be DW_TAG_subprogram_type or DW_TAG_subroutine_type.
  */
 struct ftype {
 	struct tag	 tag;
 	struct list_head parms;
+	struct list_head template_type_parms;
 	uint16_t	 nr_parms;
+	uint16_t	 nr_template_type_parms;
 	uint8_t		 unspec_parms:1; /* just one bit is needed */
 	uint8_t		 optimized_parms:1;
 	uint8_t		 processed:1;
@@ -872,6 +889,8 @@ void ftype__delete(struct ftype *ftype);
 	list_for_each_entry_safe_reverse(pos, n, &(ftype)->parms, tag.node)
 
 void ftype__add_parameter(struct ftype *ftype, struct parameter *parm);
+void ftype__add_template_type_parameter(struct ftype *ftype, struct template_type_parameter *parm);
+
 size_t ftype__fprintf(const struct ftype *ftype, const struct cu *cu,
 		      const char *name, const int inlined,
 		      const int is_pointer, const int type_spacing, bool is_prototype,



[Index of Archives]     [Linux Samsung SoC]     [Linux Rockchip SoC]     [Linux Actions SoC]     [Linux for Synopsys ARC Processors]     [Linux NFS]     [Linux NILFS]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]


  Powered by Linux