Re: Encountered error while encoding BTF due to Unsupported DW_TAG_unspecified_type(0x3b)

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

 





On 10/11/22 6:45 AM, Arnaldo Carvalho de Melo wrote:
Em Mon, Oct 10, 2022 at 10:57:24PM -0700, Yonghong Song escreveu:
On 10/10/22 1:19 PM, Arnaldo Carvalho de Melo wrote:
+++ b/btf_encoder.c
@@ -593,6 +593,19 @@ static int32_t btf_encoder__add_func_param(struct btf_encoder *encoder, const ch
   	}
   }
+static int32_t btf_encoder__tag_type(struct btf_encoder *encoder, uint32_t type_id_off, uint32_t tag_type)
+{
+	if (tag_type == 0)
+		return 0;
+
+	if (encoder->cu->unspecified_type.tag && tag_type == encoder->cu->unspecified_type.type) {

Why we need tag_type == encoder->cu->unspecified_type.type?
Should we unconditionally convert an unspecified_type to btf type id 0?

right, that is what is being done on that line, see,
DW_TAG_unspecified_type isn't some constant, what we have as the type in
functions in DWARF is the ID for that DW_TAG_unspecified_type for that
specific CU, see:

          <0><c>: Abbrev Number: 1 (DW_TAG_compile_unit)
             <d>   DW_AT_stmt_list   : 0
             <11>   DW_AT_low_pc      : 0
             <19>   DW_AT_high_pc     : 19
             <1a>   DW_AT_name        : (indirect string, offset: 0): arch/x86/entry/entry.S
             <1e>   DW_AT_comp_dir    : (indirect string, offset: 0x17): /root/git/linux
             <22>   DW_AT_producer    : (indirect string, offset: 0x27): GNU AS 2.39.50
             <26>   DW_AT_language    : 32769  (MIPS assembler)
          <1><28>: Abbrev Number: 2 (DW_TAG_subprogram)
             <29>   DW_AT_name        : (indirect string, offset: 0x36): entry_ibpb
             <2d>   DW_AT_external    : 1
             <2d>   DW_AT_type        : <0x37>
             <2e>   DW_AT_low_pc      : 0
             <36>   DW_AT_high_pc     : 19
          <1><37>: Abbrev Number: 3 (DW_TAG_unspecified_type)
          <1><38>: Abbrev Number: 0

Look at the info for entry_ibpb, there is no DW_TAG_unspecified_type
there, what it has is 0x37 as its type. We have to go see what that type
is, it could be DW_TAG_pointer_type with a DW_AT_type pointing to the
real type (or a series of references via DW_TAG_const_type,
DW_TAG_volatile_type, etc).

So in the DWARF loader we record if we have a DW_TAG_unspecified_type in
the current CU and what is its "small id", which won't be 0x37, as we
use an array for types, to compress the ID space.

Then, at the btf_encoding phase we look at functions type, and if it
matches the DW_TAG_unspecified_type type for that specific CU, then we
convert it to void.

Thanks for explanation. Now I understand.

encoder->cu->unspecified_type.tag indicates that at cu level, we have an
unspecified type.

encoder->cu->unspecified_type.type records the unspecified_type small_id. I assume this should be okay since compiler did dedup
within the cu so we should have only one unspecified type per cu.

tag_type == encoder->cu->unspecified_type.type ensures the
current btf type should expect the unspecified type before it
can be considered as an unspecified type.

Acked-by: Yonghong Song <yhs@xxxxxx>


- Arnaldo
+		// No provision for encoding this, turn it into void.
+		return 0;
+	}
+
+	return type_id_off + tag_type;
+}
+
   static int32_t btf_encoder__add_func_proto(struct btf_encoder *encoder, struct ftype *ftype, uint32_t type_id_off)
   {
   	struct btf *btf = encoder->btf;
@@ -603,7 +616,7 @@ static int32_t btf_encoder__add_func_proto(struct btf_encoder *encoder, struct f
   	/* add btf_type for func_proto */
   	nr_params = ftype->nr_parms + (ftype->unspec_parms ? 1 : 0);
-	type_id = ftype->tag.type == 0 ? 0 : type_id_off + ftype->tag.type;
+	type_id = btf_encoder__tag_type(encoder, type_id_off, ftype->tag.type);
   	id = btf__add_func_proto(btf, type_id);
   	if (id > 0) {
@@ -966,6 +979,15 @@ static int btf_encoder__encode_tag(struct btf_encoder *encoder, struct tag *tag,
   		return btf_encoder__add_enum_type(encoder, tag, conf_load);
   	case DW_TAG_subroutine_type:
   		return btf_encoder__add_func_proto(encoder, tag__ftype(tag), type_id_off);
+        case DW_TAG_unspecified_type:
+		/* Just don't encode this for now, converting anything with this type to void (0) instead.
+		 *
+		 * If we end up needing to encode this, one possible hack is to do as follows, as "const void".
+		 *
+		 * Returning zero means we skipped encoding a DWARF type.
+		 */
+               // btf_encoder__add_ref_type(encoder, BTF_KIND_CONST, 0, NULL, false);
+               return 0;
   	default:
   		fprintf(stderr, "Unsupported DW_TAG_%s(0x%x): type: 0x%x\n",
   			dwarf_tag_name(tag->tag), tag->tag, ref_type_id);
@@ -1487,7 +1509,7 @@ int btf_encoder__encode_cu(struct btf_encoder *encoder, struct cu *cu, struct co
   {
   	uint32_t type_id_off = btf__type_cnt(encoder->btf) - 1;
   	struct llvm_annotation *annot;
-	int btf_type_id, tag_type_id;
+	int btf_type_id, tag_type_id, skipped_types = 0;
   	uint32_t core_id;
   	struct function *fn;
   	struct tag *pos;
@@ -1510,8 +1532,13 @@ int btf_encoder__encode_cu(struct btf_encoder *encoder, struct cu *cu, struct co
   	cu__for_each_type(cu, core_id, pos) {
   		btf_type_id = btf_encoder__encode_tag(encoder, pos, type_id_off, conf_load);
+		if (btf_type_id == 0) {
+			++skipped_types;
+			continue;
+		}
+
   		if (btf_type_id < 0 ||
-		    tag__check_id_drift(pos, core_id, btf_type_id, type_id_off)) {
+		    tag__check_id_drift(pos, core_id, btf_type_id + skipped_types, type_id_off)) {
   			err = -1;
   			goto out;
   		}





[Index of Archives]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux