Arnaldo Carvalho de Melo 5acd1ae
From b55a35326c9ea1cd9287a7ce87193443bb523c9b Mon Sep 17 00:00:00 2001
Arnaldo Carvalho de Melo 5acd1ae
From: Arnaldo Carvalho de Melo <acme@redhat.com>
Arnaldo Carvalho de Melo 5acd1ae
Date: Mon, 10 Oct 2022 11:20:07 -0300
Arnaldo Carvalho de Melo 5acd1ae
Subject: [PATCH 6/7] btf_encoder: Encode DW_TAG_unspecified_type returning
Arnaldo Carvalho de Melo 5acd1ae
 routines as void
Arnaldo Carvalho de Melo 5acd1ae
MIME-Version: 1.0
Arnaldo Carvalho de Melo 5acd1ae
Content-Type: text/plain; charset=UTF-8
Arnaldo Carvalho de Melo 5acd1ae
Content-Transfer-Encoding: 8bit
Arnaldo Carvalho de Melo 5acd1ae
Arnaldo Carvalho de Melo 5acd1ae
Since we don´t have how to encode this info in BTF, and from what we
Arnaldo Carvalho de Melo 5acd1ae
saw, at least in this case:
Arnaldo Carvalho de Melo 5acd1ae
Arnaldo Carvalho de Melo 5acd1ae
Built binutils from git://sourceware.org/git/binutils-gdb.git, then used
Arnaldo Carvalho de Melo 5acd1ae
gcc's -B option to point to the directory with the new as, that is built
Arnaldo Carvalho de Melo 5acd1ae
as as-new, so make a symlink, ending up with:
Arnaldo Carvalho de Melo 5acd1ae
Arnaldo Carvalho de Melo 5acd1ae
  15e20ce2324a:~/git/linux # readelf -wi ./arch/x86/entry/entry.o
Arnaldo Carvalho de Melo 5acd1ae
  Contents of the .debug_info section:
Arnaldo Carvalho de Melo 5acd1ae
Arnaldo Carvalho de Melo 5acd1ae
    Compilation Unit @ offset 0:
Arnaldo Carvalho de Melo 5acd1ae
     Length:        0x35 (32-bit)
Arnaldo Carvalho de Melo 5acd1ae
     Version:       5
Arnaldo Carvalho de Melo 5acd1ae
     Unit Type:     DW_UT_compile (1)
Arnaldo Carvalho de Melo 5acd1ae
     Abbrev Offset: 0
Arnaldo Carvalho de Melo 5acd1ae
     Pointer Size:  8
Arnaldo Carvalho de Melo 5acd1ae
   <0><c>: Abbrev Number: 1 (DW_TAG_compile_unit)
Arnaldo Carvalho de Melo 5acd1ae
      <d>   DW_AT_stmt_list   : 0
Arnaldo Carvalho de Melo 5acd1ae
      <11>   DW_AT_low_pc      : 0
Arnaldo Carvalho de Melo 5acd1ae
      <19>   DW_AT_high_pc     : 19
Arnaldo Carvalho de Melo 5acd1ae
      <1a>   DW_AT_name        : (indirect string, offset: 0): arch/x86/entry/entry.S
Arnaldo Carvalho de Melo 5acd1ae
      <1e>   DW_AT_comp_dir    : (indirect string, offset: 0x17): /root/git/linux
Arnaldo Carvalho de Melo 5acd1ae
      <22>   DW_AT_producer    : (indirect string, offset: 0x27): GNU AS 2.39.50
Arnaldo Carvalho de Melo 5acd1ae
      <26>   DW_AT_language    : 32769  (MIPS assembler)
Arnaldo Carvalho de Melo 5acd1ae
   <1><28>: Abbrev Number: 2 (DW_TAG_subprogram)
Arnaldo Carvalho de Melo 5acd1ae
      <29>   DW_AT_name        : (indirect string, offset: 0x36): entry_ibpb
Arnaldo Carvalho de Melo 5acd1ae
      <2d>   DW_AT_external    : 1
Arnaldo Carvalho de Melo 5acd1ae
      <2d>   DW_AT_type        : <0x37>
Arnaldo Carvalho de Melo 5acd1ae
      <2e>   DW_AT_low_pc      : 0
Arnaldo Carvalho de Melo 5acd1ae
      <36>   DW_AT_high_pc     : 19
Arnaldo Carvalho de Melo 5acd1ae
   <1><37>: Abbrev Number: 3 (DW_TAG_unspecified_type)
Arnaldo Carvalho de Melo 5acd1ae
   <1><38>: Abbrev Number: 0
Arnaldo Carvalho de Melo 5acd1ae
Arnaldo Carvalho de Melo 5acd1ae
So we have that asm label encoded by GNU AS 2.39.50 as a
Arnaldo Carvalho de Melo 5acd1ae
DW_TAG_subprogram that has as its DW_AT_type the DW_TAG_unspecified_type
Arnaldo Carvalho de Melo 5acd1ae
0x37 that we convert to 0 (void):
Arnaldo Carvalho de Melo 5acd1ae
Arnaldo Carvalho de Melo 5acd1ae
  15e20ce2324a:~/git/linux # pahole -J ./arch/x86/entry/entry.o
Arnaldo Carvalho de Melo 5acd1ae
  15e20ce2324a:~/git/linux # pahole -JV ./arch/x86/entry/entry.o
Arnaldo Carvalho de Melo 5acd1ae
  btf_encoder__new: 'entry.o' doesn't have '.data..percpu' section
Arnaldo Carvalho de Melo 5acd1ae
  Found 0 per-CPU variables!
Arnaldo Carvalho de Melo 5acd1ae
  Found 1 functions!
Arnaldo Carvalho de Melo 5acd1ae
  File entry.o:
Arnaldo Carvalho de Melo 5acd1ae
  [1] FUNC_PROTO (anon) return=0 args=(void)
Arnaldo Carvalho de Melo 5acd1ae
  [2] FUNC entry_ibpb type_id=1
Arnaldo Carvalho de Melo 5acd1ae
  15e20ce2324a:~/git/linux # pfunct -F btf ./arch/x86/entry/entry.o
Arnaldo Carvalho de Melo 5acd1ae
  entry_ibpb
Arnaldo Carvalho de Melo 5acd1ae
  15e20ce2324a:~/git/linux # pfunct --proto -F btf ./arch/x86/entry/entry.o
Arnaldo Carvalho de Melo 5acd1ae
  void  entry_ibpb(void);
Arnaldo Carvalho de Melo 5acd1ae
  15e20ce2324a:~/git/linux #
Arnaldo Carvalho de Melo 5acd1ae
Arnaldo Carvalho de Melo 5acd1ae
  15e20ce2324a:~/git/linux # tools/bpf/bpftool/bpftool btf dump file ./arch/x86/entry/entry.o format raw
Arnaldo Carvalho de Melo 5acd1ae
  [1] FUNC_PROTO '(anon)' ret_type_id=0 vlen=0
Arnaldo Carvalho de Melo 5acd1ae
  [2] FUNC 'entry_ibpb' type_id=1 linkage=static
Arnaldo Carvalho de Melo 5acd1ae
  15e20ce2324a:~/git/linux #
Arnaldo Carvalho de Melo 5acd1ae
Arnaldo Carvalho de Melo 5acd1ae
I think this is what can be done to avoid having to skip ASM DWARF when
Arnaldo Carvalho de Melo 5acd1ae
gets widely used, i.e. binutils gets updated.
Arnaldo Carvalho de Melo 5acd1ae
Arnaldo Carvalho de Melo 5acd1ae
Acked-by: Yonghong Song <yhs@fb.com>
Arnaldo Carvalho de Melo 5acd1ae
Cc: Andrii Nakryiko <andrii.nakryiko@gmail.com>,
Arnaldo Carvalho de Melo 5acd1ae
Cc: Martin Liška <mliska@suse.cz>
Arnaldo Carvalho de Melo 5acd1ae
Link: https://lore.kernel.org/all/Y0R7uu3s%2FimnvPzM@kernel.org/
Arnaldo Carvalho de Melo 5acd1ae
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Arnaldo Carvalho de Melo 5acd1ae
---
Arnaldo Carvalho de Melo 5acd1ae
 btf_encoder.c | 33 ++++++++++++++++++++++++++++++---
Arnaldo Carvalho de Melo 5acd1ae
 1 file changed, 30 insertions(+), 3 deletions(-)
Arnaldo Carvalho de Melo 5acd1ae
Arnaldo Carvalho de Melo 5acd1ae
diff --git a/btf_encoder.c b/btf_encoder.c
Arnaldo Carvalho de Melo 5acd1ae
index e74862cfc0a3a802..eee55a0ade5e74ee 100644
Arnaldo Carvalho de Melo 5acd1ae
--- a/btf_encoder.c
Arnaldo Carvalho de Melo 5acd1ae
+++ b/btf_encoder.c
Arnaldo Carvalho de Melo 5acd1ae
@@ -570,6 +570,19 @@ static int32_t btf_encoder__add_func_param(struct btf_encoder *encoder, const ch
Arnaldo Carvalho de Melo 5acd1ae
 	}
Arnaldo Carvalho de Melo 5acd1ae
 }
Arnaldo Carvalho de Melo 5acd1ae
 
Arnaldo Carvalho de Melo 5acd1ae
+static int32_t btf_encoder__tag_type(struct btf_encoder *encoder, uint32_t type_id_off, uint32_t tag_type)
Arnaldo Carvalho de Melo 5acd1ae
+{
Arnaldo Carvalho de Melo 5acd1ae
+	if (tag_type == 0)
Arnaldo Carvalho de Melo 5acd1ae
+		return 0;
Arnaldo Carvalho de Melo 5acd1ae
+
Arnaldo Carvalho de Melo 5acd1ae
+	if (encoder->cu->unspecified_type.tag && tag_type == encoder->cu->unspecified_type.type) {
Arnaldo Carvalho de Melo 5acd1ae
+		// No provision for encoding this, turn it into void.
Arnaldo Carvalho de Melo 5acd1ae
+		return 0;
Arnaldo Carvalho de Melo 5acd1ae
+	}
Arnaldo Carvalho de Melo 5acd1ae
+
Arnaldo Carvalho de Melo 5acd1ae
+	return type_id_off + tag_type;
Arnaldo Carvalho de Melo 5acd1ae
+}
Arnaldo Carvalho de Melo 5acd1ae
+
Arnaldo Carvalho de Melo 5acd1ae
 static int32_t btf_encoder__add_func_proto(struct btf_encoder *encoder, struct ftype *ftype, uint32_t type_id_off)
Arnaldo Carvalho de Melo 5acd1ae
 {
Arnaldo Carvalho de Melo 5acd1ae
 	struct btf *btf = encoder->btf;
Arnaldo Carvalho de Melo 5acd1ae
@@ -580,7 +593,7 @@ static int32_t btf_encoder__add_func_proto(struct btf_encoder *encoder, struct f
Arnaldo Carvalho de Melo 5acd1ae
 
Arnaldo Carvalho de Melo 5acd1ae
 	/* add btf_type for func_proto */
Arnaldo Carvalho de Melo 5acd1ae
 	nr_params = ftype->nr_parms + (ftype->unspec_parms ? 1 : 0);
Arnaldo Carvalho de Melo 5acd1ae
-	type_id = ftype->tag.type == 0 ? 0 : type_id_off + ftype->tag.type;
Arnaldo Carvalho de Melo 5acd1ae
+	type_id = btf_encoder__tag_type(encoder, type_id_off, ftype->tag.type);
Arnaldo Carvalho de Melo 5acd1ae
 
Arnaldo Carvalho de Melo 5acd1ae
 	id = btf__add_func_proto(btf, type_id);
Arnaldo Carvalho de Melo 5acd1ae
 	if (id > 0) {
Arnaldo Carvalho de Melo 5acd1ae
@@ -943,6 +956,15 @@ static int btf_encoder__encode_tag(struct btf_encoder *encoder, struct tag *tag,
Arnaldo Carvalho de Melo 5acd1ae
 		return btf_encoder__add_enum_type(encoder, tag, conf_load);
Arnaldo Carvalho de Melo 5acd1ae
 	case DW_TAG_subroutine_type:
Arnaldo Carvalho de Melo 5acd1ae
 		return btf_encoder__add_func_proto(encoder, tag__ftype(tag), type_id_off);
Arnaldo Carvalho de Melo 5acd1ae
+        case DW_TAG_unspecified_type:
Arnaldo Carvalho de Melo 5acd1ae
+		/* Just don't encode this for now, converting anything with this type to void (0) instead.
Arnaldo Carvalho de Melo 5acd1ae
+		 *
Arnaldo Carvalho de Melo 5acd1ae
+		 * If we end up needing to encode this, one possible hack is to do as follows, as "const void".
Arnaldo Carvalho de Melo 5acd1ae
+		 *
Arnaldo Carvalho de Melo 5acd1ae
+		 * Returning zero means we skipped encoding a DWARF type.
Arnaldo Carvalho de Melo 5acd1ae
+		 */
Arnaldo Carvalho de Melo 5acd1ae
+               // btf_encoder__add_ref_type(encoder, BTF_KIND_CONST, 0, NULL, false);
Arnaldo Carvalho de Melo 5acd1ae
+               return 0;
Arnaldo Carvalho de Melo 5acd1ae
 	default:
Arnaldo Carvalho de Melo 5acd1ae
 		fprintf(stderr, "Unsupported DW_TAG_%s(0x%x): type: 0x%x\n",
Arnaldo Carvalho de Melo 5acd1ae
 			dwarf_tag_name(tag->tag), tag->tag, ref_type_id);
Arnaldo Carvalho de Melo 5acd1ae
@@ -1464,7 +1486,7 @@ int btf_encoder__encode_cu(struct btf_encoder *encoder, struct cu *cu, struct co
Arnaldo Carvalho de Melo 5acd1ae
 {
Arnaldo Carvalho de Melo 5acd1ae
 	uint32_t type_id_off = btf__type_cnt(encoder->btf) - 1;
Arnaldo Carvalho de Melo 5acd1ae
 	struct llvm_annotation *annot;
Arnaldo Carvalho de Melo 5acd1ae
-	int btf_type_id, tag_type_id;
Arnaldo Carvalho de Melo 5acd1ae
+	int btf_type_id, tag_type_id, skipped_types = 0;
Arnaldo Carvalho de Melo 5acd1ae
 	uint32_t core_id;
Arnaldo Carvalho de Melo 5acd1ae
 	struct function *fn;
Arnaldo Carvalho de Melo 5acd1ae
 	struct tag *pos;
Arnaldo Carvalho de Melo 5acd1ae
@@ -1487,8 +1509,13 @@ int btf_encoder__encode_cu(struct btf_encoder *encoder, struct cu *cu, struct co
Arnaldo Carvalho de Melo 5acd1ae
 	cu__for_each_type(cu, core_id, pos) {
Arnaldo Carvalho de Melo 5acd1ae
 		btf_type_id = btf_encoder__encode_tag(encoder, pos, type_id_off, conf_load);
Arnaldo Carvalho de Melo 5acd1ae
 
Arnaldo Carvalho de Melo 5acd1ae
+		if (btf_type_id == 0) {
Arnaldo Carvalho de Melo 5acd1ae
+			++skipped_types;
Arnaldo Carvalho de Melo 5acd1ae
+			continue;
Arnaldo Carvalho de Melo 5acd1ae
+		}
Arnaldo Carvalho de Melo 5acd1ae
+
Arnaldo Carvalho de Melo 5acd1ae
 		if (btf_type_id < 0 ||
Arnaldo Carvalho de Melo 5acd1ae
-		    tag__check_id_drift(pos, core_id, btf_type_id, type_id_off)) {
Arnaldo Carvalho de Melo 5acd1ae
+		    tag__check_id_drift(pos, core_id, btf_type_id + skipped_types, type_id_off)) {
Arnaldo Carvalho de Melo 5acd1ae
 			err = -1;
Arnaldo Carvalho de Melo 5acd1ae
 			goto out;
Arnaldo Carvalho de Melo 5acd1ae
 		}
Arnaldo Carvalho de Melo 5acd1ae
-- 
Arnaldo Carvalho de Melo 5acd1ae
2.39.1
Arnaldo Carvalho de Melo 5acd1ae