Blame SOURCES/0001-dwarves-Zero-initialize-struct-cu-in-cu__new-to-prev.patch

f65661
From b72f5188856df0abf45e1a707856bb4e4e86153c Mon Sep 17 00:00:00 2001
f65661
From: Alan Maguire <alan.maguire@oracle.com>
f65661
Date: Fri, 21 Oct 2022 16:02:03 +0100
f65661
Subject: [PATCH] dwarves: Zero-initialize struct cu in cu__new() to prevent
f65661
 incorrect BTF types
f65661
f65661
BTF deduplication was throwing some strange results, where core kernel
f65661
data types were failing to deduplicate due to the return values
f65661
of function type members being void (0) instead of the actual type
f65661
(unsigned int).  An example of this can be seen below, where
f65661
"struct dst_ops" was failing to deduplicate between kernel and
f65661
module:
f65661
f65661
struct dst_ops {
f65661
        short unsigned int family;
f65661
        unsigned int gc_thresh;
f65661
        int (*gc)(struct dst_ops *);
f65661
        struct dst_entry * (*check)(struct dst_entry *, __u32);
f65661
        unsigned int (*default_advmss)(const struct dst_entry *);
f65661
        unsigned int (*mtu)(const struct dst_entry *);
f65661
...
f65661
f65661
struct dst_ops___2 {
f65661
        short unsigned int family;
f65661
        unsigned int gc_thresh;
f65661
        int (*gc)(struct dst_ops___2 *);
f65661
        struct dst_entry___2 * (*check)(struct dst_entry___2 *, __u32);
f65661
        void (*default_advmss)(const struct dst_entry___2 *);
f65661
        void (*mtu)(const struct dst_entry___2 *);
f65661
...
f65661
f65661
This was seen with
f65661
f65661
bcc648a10cbc ("btf_encoder: Encode DW_TAG_unspecified_type returning routines as void")
f65661
f65661
...which rewrites the return value as 0 (void) when it is marked
f65661
as matching DW_TAG_unspecified_type:
f65661
f65661
static int32_t btf_encoder__tag_type(struct btf_encoder *encoder, uint32_t type_id_off, uint32_t tag_type)
f65661
{
f65661
       if (tag_type == 0)
f65661
               return 0;
f65661
f65661
       if (encoder->cu->unspecified_type.tag && tag_type == encoder->cu->unspecified_type.type) {
f65661
               // No provision for encoding this, turn it into void.
f65661
               return 0;
f65661
       }
f65661
f65661
       return type_id_off + tag_type;
f65661
}
f65661
f65661
However the odd thing was that on further examination, the unspecified type
f65661
was not being set, so why was this logic being tripped?  Futher debugging
f65661
showed that the encoder->cu->unspecified_type.tag value was garbage, and
f65661
the type id happened to collide with "unsigned int"; as a result we
f65661
were replacing unsigned ints with void return values, and since this
f65661
was being done to function type members in structs, it triggered a
f65661
type mismatch which failed deduplication between kernel and module.
f65661
f65661
The fix is simply to calloc() the cu in cu__new() instead.
f65661
f65661
Committer notes:
f65661
f65661
We have zalloc(size) as an alias to calloc(1, size), use it instead.
f65661
f65661
Fixes: bcc648a10cbcd0b9 ("btf_encoder: Encode DW_TAG_unspecified_type returning routines as void")
f65661
Signed-off-by: Alan Maguire <alan.maguire@oracle.com>
f65661
Acked-by: Andrii Nakryiko <andrii@kernel.org>
f65661
Acked-by: Jiri Olsa <jolsa@kernel.org>
f65661
Cc: bpf@vger.kernel.org
f65661
Cc: dwarves@vger.kernel.org
f65661
Link: https://lore.kernel.org/r/1666364523-9648-1-git-send-email-alan.maguire@oracle.com
f65661
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
f65661
---
f65661
 dwarves.c | 2 +-
f65661
 1 file changed, 1 insertion(+), 1 deletion(-)
f65661
f65661
diff --git a/dwarves.c b/dwarves.c
f65661
index fbebc1d..95a3bac 100644
f65661
--- a/dwarves.c
f65661
+++ b/dwarves.c
f65661
@@ -626,7 +626,7 @@ struct cu *cu__new(const char *name, uint8_t addr_size,
f65661
 		   const unsigned char *build_id, int build_id_len,
f65661
 		   const char *filename, bool use_obstack)
f65661
 {
f65661
-	struct cu *cu = malloc(sizeof(*cu) + build_id_len);
f65661
+	struct cu *cu = zalloc(sizeof(*cu) + build_id_len);
f65661
 
f65661
 	if (cu != NULL) {
f65661
 		uint32_t void_id;
f65661
-- 
f65661
2.38.1
f65661