From: Hao Luo <haoluo-hpIqsD4AKlfQT0dZR+AlfA@public.gmane.org>
To: Arnaldo Carvalho de Melo
<arnaldo.melo-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
Cc: Andrii Nakryiko
<andrii.nakryiko-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>,
Alexei Starovoitov
<alexei.starovoitov-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>,
daniel-FeC+5ew28dpmcu3hnIyYJQ@public.gmane.org,
olegrom-hpIqsD4AKlfQT0dZR+AlfA@public.gmane.org,
kafai-b10kYP2dOMg@public.gmane.org,
dwarves-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
Hao Luo <haoluo-hpIqsD4AKlfQT0dZR+AlfA@public.gmane.org>
Subject: [PATCH] btf_encoder: Teach pahole to store percpu variables in vmlinux BTF.
Date: Thu, 28 May 2020 18:13:05 -0700 [thread overview]
Message-ID: <20200529011305.35132-1-haoluo@google.com> (raw)
On SMP systems, the global percpu variables are placed in a speical
'.data..percpu' section, which is stored in a segment whose initial
address is set to 0, the addresses of per-CPU variables are relative
positive addresses[1].
This patch extracts these variables from vmlinux and places them with
their type information in BTF, so that they can be accessed in BPF.
In a v5.7-rc7 linux kernel, I was able to extract 291 such variables.
The space overhead is small.
Testing:
Before:
$ readelf -SW vmlinux | grep BTF
[25] .BTF PROGBITS ffffffff821a905c 13a905c 2d2bf8 00 A 0 0 1
After:
$ pahole -J vmlinux
$ readelf -SW vmlinux | grep BTF
[25] .BTF PROGBITS ffffffff821a905c 13a905c 2d4db8 00 A 0 0 1
Common percpu vars can be found in the BTF section.
$ bpftool btf dump file vmlinux | grep runqueues
[14098] VAR 'runqueues' type_id=13725, linkage=global-alloc
$ bpftool btf dump file vmlinux | grep cpu_stopper
[17589] STRUCT 'cpu_stopper' size=72 vlen=5
[17609] VAR 'cpu_stopper' type_id=17589, linkage=global-alloc
References:
[1] https://lwn.net/Articles/531148/
Signed-off-by: Hao Luo <haoluo-hpIqsD4AKlfQT0dZR+AlfA@public.gmane.org>
---
btf_encoder.c | 27 +++++++++++++++++++++++++++
libbtf.c | 29 +++++++++++++++++++++++++++++
libbtf.h | 2 ++
pahole.c | 1 +
4 files changed, 59 insertions(+)
diff --git a/btf_encoder.c b/btf_encoder.c
index df16ba0..f550f34 100644
--- a/btf_encoder.c
+++ b/btf_encoder.c
@@ -241,6 +241,33 @@ int cu__encode_btf(struct cu *cu, int verbose)
}
}
+ cu__for_each_variable(cu, core_id, pos) {
+ int btf_var_id;
+ struct variable *var;
+ uint32_t linkage;
+
+ var = tag__variable(pos);
+ /*
+ * .data..percpu is stored in a segment whose initial address is
+ * set to 0, the addresses of per-CPU variables are addresses
+ * relative to 0.
+ *
+ * https://lwn.net/Articles/531148/
+ */
+ if ((int64_t)var->ip.addr <= 0)
+ continue;
+ linkage = variable__scope(var) == VSCOPE_GLOBAL;
+ btf_var_id = btf_elf__add_var_type(btfe, var->ip.tag.type,
+ var->name, linkage,
+ type_id_off);
+ if (btf_var_id < 0) {
+ err = -1;
+ printf("error: failed to encode variable '%s'\n",
+ variable__name(var, cu));
+ goto out;
+ }
+ }
+
out:
if (err)
btf_elf__delete(btfe);
diff --git a/libbtf.c b/libbtf.c
index 2fbce40..de85666 100644
--- a/libbtf.c
+++ b/libbtf.c
@@ -613,6 +613,35 @@ int32_t btf_elf__add_func_proto(struct btf_elf *btfe, struct ftype *ftype, uint3
return type_id;
}
+int32_t btf_elf__add_var_type(struct btf_elf *btfe, uint32_t type,
+ uint32_t name_off, uint32_t linkage,
+ uint32_t type_id_off)
+{
+ struct {
+ struct btf_type type;
+ struct btf_var var;
+ } t;
+
+ t.type.name_off = name_off;
+ t.type.info = BTF_INFO_ENCODE(BTF_KIND_VAR, 0, 0);
+ t.type.type = type_id_off + type;
+
+ t.var.linkage = linkage;
+
+ ++btfe->type_index;
+ if (gobuffer__add(&btfe->types, &t.type, sizeof(t)) < 0) {
+ btf_elf__log_type(btfe, &t.type, true, true,
+ "type=%u name=%s Error in adding gobuffer",
+ t.type.type, btf_elf__name_in_gobuf(btfe, t.type.name_off));
+ return -1;
+ }
+
+ btf_elf__log_type(btfe, &t.type, false, false, "type=%u name=%s",
+ t.type.type, btf_elf__name_in_gobuf(btfe, t.type.name_off));
+
+ return btfe->type_index;
+}
+
static int btf_elf__write(const char *filename, struct btf *btf)
{
GElf_Shdr shdr_mem, *shdr;
diff --git a/libbtf.h b/libbtf.h
index f3c8500..d9e723a 100644
--- a/libbtf.h
+++ b/libbtf.h
@@ -55,6 +55,8 @@ int32_t btf_elf__add_enum(struct btf_elf *btf, uint32_t name, uint32_t size,
int btf_elf__add_enum_val(struct btf_elf *btf, uint32_t name, int32_t value);
int32_t btf_elf__add_func_proto(struct btf_elf *btf, struct ftype *ftype,
uint32_t type_id_off);
+int32_t btf_elf__add_var_type(struct btf_elf *btfe, uint32_t type, uint32_t name_off,
+ uint32_t linkage, uint32_t type_id_off);
void btf_elf__set_strings(struct btf_elf *btf, struct gobuffer *strings);
int btf_elf__encode(struct btf_elf *btf, uint8_t flags);
diff --git a/pahole.c b/pahole.c
index e2a081b..8407db9 100644
--- a/pahole.c
+++ b/pahole.c
@@ -1084,6 +1084,7 @@ static error_t pahole__options_parser(int key, char *arg,
case 'i': find_containers = 1;
class_name = arg; break;
case 'J': btf_encode = 1;
+ conf_load.get_addr_info = true;
no_bitfield_type_recode = true; break;
case 'l': conf.show_first_biggest_size_base_type_member = 1; break;
case 'M': conf.show_only_data_members = 1; break;
--
2.27.0.rc2.251.g90737beb825-goog
next reply other threads:[~2020-05-29 1:13 UTC|newest]
Thread overview: 3+ messages / expand[flat|nested] mbox.gz Atom feed top
2020-05-29 1:13 Hao Luo [this message]
[not found] ` <20200529011305.35132-1-haoluo-hpIqsD4AKlfQT0dZR+AlfA@public.gmane.org>
2020-05-29 5:19 ` [PATCH] btf_encoder: Teach pahole to store percpu variables in vmlinux BTF Andrii Nakryiko
[not found] ` <CAEf4BzYd=26j_5RWxfVVq=4DrzEc62gQChX94mUabxturBpRdg-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2020-05-29 15:31 ` Arnaldo Carvalho de Melo
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=20200529011305.35132-1-haoluo@google.com \
--to=haoluo-hpiqsd4aklfqt0dzr+alfa@public.gmane.org \
--cc=alexei.starovoitov-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org \
--cc=andrii.nakryiko-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org \
--cc=arnaldo.melo-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org \
--cc=daniel-FeC+5ew28dpmcu3hnIyYJQ@public.gmane.org \
--cc=dwarves-u79uwXL29TY76Z2rM5mHXA@public.gmane.org \
--cc=kafai-b10kYP2dOMg@public.gmane.org \
--cc=olegrom-hpIqsD4AKlfQT0dZR+AlfA@public.gmane.org \
/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).