Received: by 2002:a05:6a10:22f:0:0:0:0 with SMTP id 15csp1934326pxk; Tue, 1 Sep 2020 11:12:18 -0700 (PDT) X-Google-Smtp-Source: ABdhPJzQBhU6/C0fsIMYVTIp+7vlZoew1bYzf1gK0vC653rHXbcXY6ns3ZRVHnkM/nY/HoPrPhap X-Received: by 2002:aa7:d284:: with SMTP id w4mr3073381edq.258.1598983938107; Tue, 01 Sep 2020 11:12:18 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1598983938; cv=none; d=google.com; s=arc-20160816; b=PLJFx2wHG5q3PLUXP/IEVYkX+I9GPGepQiv99BGKW96/t4b8p0IZsd5yzavh3SFC7z HRgwy8zcGMmnHOTVTZMx4x4acr+un1cmhZkSJ7uLe8USXTwbbU2eCD4wibKoMgrvFwJS vpIEzzTIFG/wzvK+uTaWN+naLftdzxGtFWBDYfQ3lcz0j5t0qjjFKn6GnbpUD96jLQeh 6D6wittzv1YPI1zaVjO0DTG+xEuiTpUXCzv6kdRCutF08rJdSMJSxwT/Si5inRid75AD Zmq7Q9Hqs7rRldLyQ0dWYuArF/xUm3xTVenjBkY9Y4MgO3RYIDswEh1oJtaU7H3lSjNm efTg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:cc:to:subject:message-id:date:from :in-reply-to:references:mime-version:dkim-signature; bh=MSyQm4hBeFyUcS6RfecsGKRclkyWgLleS2YbMFdqO5c=; b=haiwYOMsMRJf0xRkUK9RBHkKSlu0tKEErkvKue9/8fE0faP1RJ6dq/AQd3H1aGUp3A 5bdcx+XXsRPSi1WA4Mrke7tRohk681UlNM4016kYViw4r9D9jne56Lzv+Ty8F1pkwx+8 bfWPQAqtAlit7Y/VTY7aglZ4o4erydxSBNBB53KBeQZmAWDvIj2EvCCkv2t+zquWV4jN xEPwU9+LkwFKd9zSBUzpqjjR6bHaFVc0zzvsfNOTjekQx6b+dnKv5NS02V3flUDZ8kn4 2OyBdXFERoCggm/6BxA2Y+ZjOyZuqnXeFWrKc/sDhsZ7fwgmpFX2M7beO7fiOkZ1aiuK VcgA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@gmail.com header.s=20161025 header.b=mPnqp0wZ; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=QUARANTINE dis=NONE) header.from=gmail.com Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id y14si1018377edo.347.2020.09.01.11.11.53; Tue, 01 Sep 2020 11:12:18 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) client-ip=23.128.96.18; Authentication-Results: mx.google.com; dkim=pass header.i=@gmail.com header.s=20161025 header.b=mPnqp0wZ; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=QUARANTINE dis=NONE) header.from=gmail.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729239AbgIASLU (ORCPT + 99 others); Tue, 1 Sep 2020 14:11:20 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:50974 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726377AbgIASLT (ORCPT ); Tue, 1 Sep 2020 14:11:19 -0400 Received: from mail-yb1-xb44.google.com (mail-yb1-xb44.google.com [IPv6:2607:f8b0:4864:20::b44]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id DCFD8C061244; Tue, 1 Sep 2020 11:11:18 -0700 (PDT) Received: by mail-yb1-xb44.google.com with SMTP id c17so1349639ybe.0; Tue, 01 Sep 2020 11:11:18 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=mime-version:references:in-reply-to:from:date:message-id:subject:to :cc; bh=MSyQm4hBeFyUcS6RfecsGKRclkyWgLleS2YbMFdqO5c=; b=mPnqp0wZ+H2I178EEOKPt+nZ8xjZmfTYGPuhQfnyAQ3lCUniYWfI5k7ARYyFFLj2l4 4idYaOqkr4Cq6ol5geyJdQGsa7UJ4+63D0j2SbdHwo7xZavxYHrEOQfW97rfqlyvRqFz mSaCKNo+Fp8XLc9yz0q3OHZSHJB8M2QdeRBXWvJo4HwIXbLw73K/281UQBGY7U7E/QUo T25VtbCcK+RPftLHIHu3qHrdFQtzgeltS7Qb6RpiV0HEiJoDjTbiOgZhh3ue63oTAmNy 3y7bYj0t2xbKMXz5ToqMBV69rOVBt8Tu3GaPQdugYgZ0aCdskt3pzr+hRp+g2ZhWe2VA qA6w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:mime-version:references:in-reply-to:from:date :message-id:subject:to:cc; bh=MSyQm4hBeFyUcS6RfecsGKRclkyWgLleS2YbMFdqO5c=; b=GEc5cJBFHzWW7mOaBdOBi07euKGpJkLQswK8SMrdCKRmn6wGaSKRRr8jHJ+a6V2Isp tQ7TB/8QzDa4DM3K1T0K59jAdmJ1NEaNrt9Oj7FGomjjuCimt1WlqXOUpc0W7+OD0yNF ubYZFUThgLq/zqBkgGN5rBOKI/CnZ+DOB5l/2fkahAUqYziVNtpirAu9JVR4KeOPHo3m AnQkUuldcAkEGPqqszJmTUBEnetY1NgxdIRPFSwcOfJ4lHOfH2iW2Rk6oHvJkwMK0uuD wT2Mx2PjVqWd50NQwley/Wvo/2Tl3lM80wmCq2M809bsAxLDxOHdpo15Q4bFRrrSHH4Q I6pA== X-Gm-Message-State: AOAM532xUWhK9DG/3G0+/V+FjkneKb93USJrgysV5UqXQYGKpMFnfAxN f7Oyf/gfSPsBrtVrPBFa8JSPBIbbDQ4G49qGCtlA9VlTC/s= X-Received: by 2002:a25:c4c2:: with SMTP id u185mr4826837ybf.347.1598983877702; Tue, 01 Sep 2020 11:11:17 -0700 (PDT) MIME-Version: 1.0 References: <20200819224030.1615203-1-haoluo@google.com> <20200819224030.1615203-5-haoluo@google.com> In-Reply-To: From: Andrii Nakryiko Date: Tue, 1 Sep 2020 11:11:06 -0700 Message-ID: Subject: Re: [PATCH bpf-next v1 4/8] bpf/libbpf: BTF support for typed ksyms To: Hao Luo Cc: Networking , bpf , open list , "open list:KERNEL SELFTEST FRAMEWORK" , Shuah Khan , Alexei Starovoitov , Andrii Nakryiko , Daniel Borkmann , Martin KaFai Lau , Song Liu , Yonghong Song , John Fastabend , KP Singh , Quentin Monnet , Steven Rostedt , Ingo Molnar , Andrey Ignatov , Jakub Sitnicki Content-Type: text/plain; charset="UTF-8" Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org On Thu, Aug 27, 2020 at 3:29 PM Hao Luo wrote: > > On Fri, Aug 21, 2020 at 3:37 PM Andrii Nakryiko > wrote: > > > > On Wed, Aug 19, 2020 at 3:42 PM Hao Luo wrote: > > > > > > If a ksym is defined with a type, libbpf will try to find the ksym's btf > > > information from kernel btf. If a valid btf entry for the ksym is found, > > > libbpf can pass in the found btf id to the verifier, which validates the > > > ksym's type and value. > > > > > > Typeless ksyms (i.e. those defined as 'void') will not have such btf_id, > > > but it has the symbol's address (read from kallsyms) and its value is > > > treated as a raw pointer. > > > > > > Signed-off-by: Hao Luo > > > --- > > > tools/lib/bpf/libbpf.c | 130 ++++++++++++++++++++++++++++++++++++----- > > > 1 file changed, 114 insertions(+), 16 deletions(-) > > > > > > diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c > > > index 4a81c6b2d21b..94eff612c7c2 100644 > > > --- a/tools/lib/bpf/libbpf.c > > > +++ b/tools/lib/bpf/libbpf.c > > > @@ -357,7 +357,16 @@ struct extern_desc { > > > bool is_signed; > > > } kcfg; > > > struct { > > > - unsigned long long addr; > > > + /* > > > + * 1. If ksym is typeless, the field 'addr' is valid. > > > + * 2. If ksym is typed, the field 'vmlinux_btf_id' is > > > + * valid. > > > + */ > > > + bool is_typeless; > > > + union { > > > + unsigned long long addr; > > > + int vmlinux_btf_id; > > > + }; > > > > ksym is 16 bytes anyways, union doesn't help to save space. I propose > > to encode all this with just two fields: vmlinux_btf_id and addr. If > > btf_id == 0, then extern is typeless. > > Ack on expanding the union. But I slightly preferred keeping > is_typeless. IIUC, btf_id points a VAR_KIND, we need the following > pointer chasing every time > > t = btf__type_by_id(obj->btf, ext->btf_id); > t->type; > > which I felt is worse than keeping a is_typeless flag. Sorry, I'm not following. In all places where you would check sym->is_typeless, you'd now just do: if (ext->ksym.vmlinux_btf_id) { /* typed, use ext->ksym.vmlinux_btf_id */ } else { /* typeless */ } > > > > > > } ksym; > > > }; > > > }; > > > @@ -382,6 +391,7 @@ struct bpf_object { > > > > > > bool loaded; > > > bool has_pseudo_calls; > > > + bool has_typed_ksyms; > > > > > > /* > > > * Information when doing elf related work. Only valid if fd > > > @@ -2521,6 +2531,10 @@ static int bpf_object__load_vmlinux_btf(struct bpf_object *obj) > > > if (obj->btf_ext && obj->btf_ext->core_relo_info.len) > > > need_vmlinux_btf = true; > > > > > > + /* Support for typed ksyms needs kernel BTF */ > > > + if (obj->has_typed_ksyms) > > > + need_vmlinux_btf = true; > > > > On the second read, I don't think you really need `has_typed_ksyms` at > > all. Just iterate over ksym externs and see if you have a typed one. > > It's the only place that cares. > > > > Ack. Will iterate over ksym externs here. > > > > + > > > bpf_object__for_each_program(prog, obj) { > > > if (!prog->load) > > > continue; > > > @@ -2975,10 +2989,10 @@ static int bpf_object__collect_externs(struct bpf_object *obj) > > > ext->type = EXT_KSYM; > > > > > > vt = skip_mods_and_typedefs(obj->btf, t->type, NULL); > > > - if (!btf_is_void(vt)) { > > > - pr_warn("extern (ksym) '%s' is not typeless (void)\n", ext_name); > > > - return -ENOTSUP; > > > - } > > > + ext->ksym.is_typeless = btf_is_void(vt); > > > + > > > + if (!obj->has_typed_ksyms && !ext->ksym.is_typeless) > > > + obj->has_typed_ksyms = true; > > > > nit: keep it simple: > > > > if (ext->ksym.is_typeless) > > obj->has_typed_ksyms = true; > > > > Ack. > > > > } else { > > > pr_warn("unrecognized extern section '%s'\n", sec_name); > > > return -ENOTSUP; > > > @@ -2992,9 +3006,9 @@ static int bpf_object__collect_externs(struct bpf_object *obj) > > > /* sort externs by type, for kcfg ones also by (align, size, name) */ > > > qsort(obj->externs, obj->nr_extern, sizeof(*ext), cmp_externs); > > > > > > - /* for .ksyms section, we need to turn all externs into allocated > > > - * variables in BTF to pass kernel verification; we do this by > > > - * pretending that each extern is a 8-byte variable > > > + /* for .ksyms section, we need to turn all typeless externs into > > > + * allocated variables in BTF to pass kernel verification; we do > > > + * this by pretending that each typeless extern is a 8-byte variable > > > */ > > > if (ksym_sec) { > > > /* find existing 4-byte integer type in BTF to use for fake > > > @@ -3012,7 +3026,7 @@ static int bpf_object__collect_externs(struct bpf_object *obj) > > > > > > sec = ksym_sec; > > > n = btf_vlen(sec); > > > - for (i = 0, off = 0; i < n; i++, off += sizeof(int)) { > > > + for (i = 0, off = 0; i < n; i++) { > > > struct btf_var_secinfo *vs = btf_var_secinfos(sec) + i; > > > struct btf_type *vt; > > > > > > @@ -3025,9 +3039,14 @@ static int bpf_object__collect_externs(struct bpf_object *obj) > > > return -ESRCH; > > > } > > > btf_var(vt)->linkage = BTF_VAR_GLOBAL_ALLOCATED; > > > - vt->type = int_btf_id; > > > + if (ext->ksym.is_typeless) { > > > + vt->type = int_btf_id; > > > + vs->size = sizeof(int); > > > + } > > > vs->offset = off; > > > - vs->size = sizeof(int); > > > + off += vs->size; > > > + pr_debug("ksym var_secinfo: var '%s', type #%d, size %d, offset %d\n", > > > + ext->name, vt->type, vs->size, vs->offset); > > > > It's a bit of a waste that we still allocate memory for those typed > > ksym externs, as they don't really need space. But modifying BTF is a > > pain right now, so I think we'll have to do it, until we have a better > > BTF API. But let's make them integers for now to take a fixed and > > small amount of space. > > > > Do you mean making typed ksym externs of type integer? If so, we can't > do that, I think. After collect_externs, we later need to compare the > declared extern's type against the type defined in kernel. Better not > rewrite their types in BTf. Then maybe we need to make btf_id to point to the actual type of the variable, not BTF_KIND_VAR? Or just additionally record type's btf_id, not sure which one makes more sense at the moment. > > I am generally against modifying BTF. I initially didn't notice that > all the ksym externs' types are modified to 'int' and the type > comparison I mentioned above always failed. I dumped the btf in > vmlinux and the btf in object file, checked the kernel variable's > source code, printed out everything I could. The experience was very > bad. > It might be confusing, I agree, but the alternative is just a waste of memory just to match the BTF definition of a DATASEC, which describes externs. It seems sloppy to allocate a bunch of unused memory just to match the kernel's variable size, while in reality we either use 8 bytes used (for typeless externs, storing ksym address) or none (for typed externs). Another alternative is to not specify BTF ID for .ksyms map, but it's not great for typeless externs case, as we are losing all type info completely. Trade-offs... [...] > > > + } > > > + > > > + id = btf__find_by_name_kind(obj->btf_vmlinux, ext->name, > > > + BTF_KIND_VAR); > > > + if (id <= 0) { > > > + pr_warn("no btf entry for ksym '%s' in vmlinux.\n", > > > + ext->name); > > > + return -ESRCH; > > > + } > > > + > > > + vx = btf__type_by_id(obj->btf_vmlinux, id); > > > + tx = skip_mods_and_typedefs(obj->btf_vmlinux, vx->type, &vtx); > > > + > > > + v = btf__type_by_id(obj->btf, ext->btf_id); > > > + t = skip_mods_and_typedefs(obj->btf, v->type, &vt); > > > + > > > + if (!btf_ksym_type_match(obj->btf_vmlinux, vtx, obj->btf, vt)) { > > > + const char *tname, *txname; /* names of TYPEs */ > > > + > > > + txname = btf__name_by_offset(obj->btf_vmlinux, tx->name_off); > > > + tname = btf__name_by_offset(obj->btf, t->name_off); > > > + > > > + pr_warn("ksym '%s' expects type '%s' (vmlinux_btf_id: #%d), " > > > + "but got '%s' (btf_id: #%d)\n", ext->name, > > > + txname, vtx, tname, vt); > > > + return -EINVAL; > > > + } > > > > yeah, definitely just use bpf_core_types_are_compat() here. You'll > > want to skip_mods_and_typedefs first, but everything else should work > > for your use case. > > > > Ack. bpf_core_types_are_compat() is indeed a perfect fit here. > ok, great > [...]