dwarves.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Yonghong Song <yhs@fb.com>
To: Arnaldo Carvalho de Melo <arnaldo.melo@gmail.com>,
	<dwarves@vger.kernel.org>
Cc: Alexei Starovoitov <ast@kernel.org>,
	Bill Wendling <morbo@google.com>, <bpf@vger.kernel.org>,
	David Blaikie <dblaikie@gmail.com>, <kernel-team@fb.com>,
	Nick Desaulniers <ndesaulniers@google.com>
Subject: [PATCH dwarves v2] dwarf_loader: handle subprogram ret type with abstract_origin properly
Date: Thu, 1 Apr 2021 16:55:34 -0700	[thread overview]
Message-ID: <20210401235534.3701191-1-yhs@fb.com> (raw)

With latest bpf-next built with clang lto (thin or full), I hit one test
failures:
  $ ./test_progs -t tcp
  ...
  libbpf: extern (func ksym) 'tcp_slow_start': func_proto [23] incompatible with kernel [115303]
  libbpf: failed to load object 'bpf_cubic'
  libbpf: failed to load BPF skeleton 'bpf_cubic': -22
  test_cubic:FAIL:bpf_cubic__open_and_load failed
  #9/2 cubic:FAIL
  ...

The reason of the failure is due to bpf program 'tcp_slow_start'
func signature is different from vmlinux BTF. bpf program uses
the following signature:
  extern __u32 tcp_slow_start(struct tcp_sock *tp, __u32 acked);
which is identical to the kernel definition in linux:include/net/tcp.h:
  u32 tcp_slow_start(struct tcp_sock *tp, u32 acked);
While vmlinux BTF definition like:
  [115303] FUNC_PROTO '(anon)' ret_type_id=0 vlen=2
          'tp' type_id=39373
          'acked' type_id=18
  [115304] FUNC 'tcp_slow_start' type_id=115303 linkage=static
The above is dumped with `bpftool btf dump file vmlinux`.
You can see the ret_type_id is 0 and this caused the problem.

Looking at dwarf, we have:

0x11f2ec67:   DW_TAG_subprogram
                DW_AT_low_pc    (0xffffffff81ed2330)
                DW_AT_high_pc   (0xffffffff81ed235c)
                DW_AT_frame_base        ()
                DW_AT_GNU_all_call_sites        (true)
                DW_AT_abstract_origin   (0x11f2ed66 "tcp_slow_start")
...
0x11f2ed66:   DW_TAG_subprogram
                DW_AT_name      ("tcp_slow_start")
                DW_AT_decl_file ("/home/yhs/work/bpf-next/net/ipv4/tcp_cong.c")
                DW_AT_decl_line (392)
                DW_AT_prototyped        (true)
                DW_AT_type      (0x11f130c2 "u32")
                DW_AT_external  (true)
                DW_AT_inline    (DW_INL_inlined)

We have a subprogram which has an abstract_origin pointing to
the subprogram prototype with return type. Current one pass
recoding cannot easily resolve this easily since
at the time recoding for 0x11f2ec67, the return type in
0x11f2ed66 has not been resolved.

To simplify implementation, I just added another pass to
go through all functions after recoding pass. This should
resolve the above issue.

With this patch, among total 250999 functions in vmlinux,
4821 functions needs return type adjustment from type id 0
to correct values. The above failed bpf selftest passed too.

Signed-off-by: Yonghong Song <yhs@fb.com>
---
 dwarf_loader.c | 38 ++++++++++++++++++++++++++++++++++++++
 1 file changed, 38 insertions(+)

Changelogs:
  v1 -> v2:
    . remove dead code (check abstract_origin tag must be
      a subprogram). The dwarf standard ensures this is
      the case. (David Blaikie)

diff --git a/dwarf_loader.c b/dwarf_loader.c
index 026d137..5dea837 100644
--- a/dwarf_loader.c
+++ b/dwarf_loader.c
@@ -2198,6 +2198,34 @@ out:
 	return 0;
 }
 
+static int cu__resolve_func_ret_types(struct cu *cu)
+{
+	struct ptr_table *pt = &cu->functions_table;
+	uint32_t i;
+
+	for (i = 0; i < pt->nr_entries; ++i) {
+		struct tag *tag = pt->entries[i];
+
+		if (tag == NULL || tag->type != 0)
+			continue;
+
+		struct function *fn = tag__function(tag);
+		if (!fn->abstract_origin)
+			continue;
+
+		struct dwarf_tag *dtag = tag->priv;
+		struct dwarf_tag *dfunc;
+		dfunc = dwarf_cu__find_tag_by_ref(cu->priv, &dtag->abstract_origin);
+		if (dfunc == NULL) {
+			tag__print_abstract_origin_not_found(tag);
+			return -1;
+		}
+
+		tag->type = dfunc->tag->type;
+	}
+	return 0;
+}
+
 static int cu__recode_dwarf_types_table(struct cu *cu,
 					struct ptr_table *pt,
 					uint32_t i)
@@ -2637,6 +2665,16 @@ static int cus__merge_and_process_cu(struct cus *cus, struct conf_load *conf,
 	/* process merged cu */
 	if (cu__recode_dwarf_types(cu) != LSK__KEEPIT)
 		return DWARF_CB_ABORT;
+
+	/*
+	 * for lto build, the function return type may not be
+	 * resolved due to the return type of a subprogram is
+	 * encoded in another subprogram through abstract_origin
+	 * tag. Let us visit all subprograms again to resolve this.
+	 */
+	if (cu__resolve_func_ret_types(cu) != LSK__KEEPIT)
+		return DWARF_CB_ABORT;
+
 	if (finalize_cu_immediately(cus, cu, dcu, conf)
 	    == LSK__STOP_LOADING)
 		return DWARF_CB_ABORT;
-- 
2.30.2


                 reply	other threads:[~2021-04-01 23:56 UTC|newest]

Thread overview: [no followups] expand[flat|nested]  mbox.gz  Atom feed

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=20210401235534.3701191-1-yhs@fb.com \
    --to=yhs@fb.com \
    --cc=arnaldo.melo@gmail.com \
    --cc=ast@kernel.org \
    --cc=bpf@vger.kernel.org \
    --cc=dblaikie@gmail.com \
    --cc=dwarves@vger.kernel.org \
    --cc=kernel-team@fb.com \
    --cc=morbo@google.com \
    --cc=ndesaulniers@google.com \
    /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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).