[PATCH bpf-next v2] tools/bpf: make libbpf _GNU_SOURCE friendly

2018-11-29 Thread Yonghong Song
During porting libbpf to bcc, I got some warnings like below:
  ...
  [  2%] Building C object 
src/cc/CMakeFiles/bpf-shared.dir/libbpf/src/libbpf.c.o
  /home/yhs/work/bcc2/src/cc/libbpf/src/libbpf.c:12:0:
  warning: "_GNU_SOURCE" redefined [enabled by default]
   #define _GNU_SOURCE
  ...
  [  3%] Building C object 
src/cc/CMakeFiles/bpf-shared.dir/libbpf/src/libbpf_errno.c.o
  /home/yhs/work/bcc2/src/cc/libbpf/src/libbpf_errno.c: In function 
‘libbpf_strerror’:
  /home/yhs/work/bcc2/src/cc/libbpf/src/libbpf_errno.c:45:7:
  warning: assignment makes integer from pointer without a cast [enabled by 
default]
 ret = strerror_r(err, buf, size);
  ...

bcc is built with _GNU_SOURCE defined and this caused the above warning.
This patch intends to make libpf _GNU_SOURCE friendly by
  . define _GNU_SOURCE in libbpf.c unless it is not defined
  . undefine _GNU_SOURCE as non-gnu version of strerror_r is expected.

Signed-off-by: Yonghong Song 
---
 tools/lib/bpf/libbpf.c   | 2 ++
 tools/lib/bpf/libbpf_errno.c | 1 +
 2 files changed, 3 insertions(+)

Changelog:
 v1 -> v2:
   . undef _GNU_SOURCE instead of multiversioning strerror_r,
 suggested by Jakub.

diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c
index ed4212a4c5f9..59b748ebd15f 100644
--- a/tools/lib/bpf/libbpf.c
+++ b/tools/lib/bpf/libbpf.c
@@ -9,7 +9,9 @@
  * Copyright (C) 2017 Nicira, Inc.
  */
 
+#ifndef _GNU_SOURCE
 #define _GNU_SOURCE
+#endif
 #include 
 #include 
 #include 
diff --git a/tools/lib/bpf/libbpf_errno.c b/tools/lib/bpf/libbpf_errno.c
index d83b17f8435c..4343e40588c6 100644
--- a/tools/lib/bpf/libbpf_errno.c
+++ b/tools/lib/bpf/libbpf_errno.c
@@ -7,6 +7,7 @@
  * Copyright (C) 2017 Nicira, Inc.
  */
 
+#undef _GNU_SOURCE
 #include 
 #include 
 
-- 
2.17.1



Re: [PATCH bpf-next] tools/bpf: make libbpf _GNU_SOURCE friendly

2018-11-29 Thread Yonghong Song


On 11/29/18 1:00 PM, Jakub Kicinski wrote:
> On Thu, 29 Nov 2018 12:38:03 -0800, Yonghong Song wrote:
>> diff --git a/tools/lib/bpf/libbpf_errno.c b/tools/lib/bpf/libbpf_errno.c
>> index d83b17f8435c..286e497c50ec 100644
>> --- a/tools/lib/bpf/libbpf_errno.c
>> +++ b/tools/lib/bpf/libbpf_errno.c
>> @@ -40,9 +40,19 @@ int libbpf_strerror(int err, char *buf, size_t size)
>>  err = err > 0 ? err : -err;
>>   
>>  if (err < __LIBBPF_ERRNO__START) {
>> +#ifdef _GNU_SOURCE
>> +const char *ret_buf;
>> +#endif
>>  int ret;
>>   
>> +#ifdef _GNU_SOURCE
>> +ret_buf = strerror_r(err, buf, size);
>> +if (ret_buf != buf)
>> +snprintf(buf, size, "%s", ret_buf);
>> +ret = 0;
>> +#else
>>  ret = strerror_r(err, buf, size);
>> +#endif
>>  buf[size - 1] = '\0';
>>  return ret;
>>  }
> 
> That is kinda strange, the whole point for this file was to have
> non-GNU strerror_r, would doing #undef _GNU_SOURCE at the top not work?

Thanks for suggestion as I did not the history of this file.
Yes, #undef _GNU_SOURCE works. Will send a revision shortly.


[PATCH bpf-next] tools/bpf: make libbpf _GNU_SOURCE friendly

2018-11-29 Thread Yonghong Song
During porting libbpf to bcc, I got some warnings like below:
  ...
  [  2%] Building C object 
src/cc/CMakeFiles/bpf-shared.dir/libbpf/src/libbpf.c.o
  /home/yhs/work/bcc2/src/cc/libbpf/src/libbpf.c:12:0:
  warning: "_GNU_SOURCE" redefined [enabled by default]
   #define _GNU_SOURCE
  ...
  [  3%] Building C object 
src/cc/CMakeFiles/bpf-shared.dir/libbpf/src/libbpf_errno.c.o
  /home/yhs/work/bcc2/src/cc/libbpf/src/libbpf_errno.c: In function 
‘libbpf_strerror’:
  /home/yhs/work/bcc2/src/cc/libbpf/src/libbpf_errno.c:45:7:
  warning: assignment makes integer from pointer without a cast [enabled by 
default]
 ret = strerror_r(err, buf, size);
  ...

bcc is built with _GNU_SOURCE defined and this caused the above warning.
This patch intends to make libpf _GNU_SOURCE friendly by
  . define _GNU_SOURCE unless it is not defined
  . gnu version strerror_r has different return value than non-gnu version,
so strerror_r return value is handled differently if _GNU_SOURCE is defined.

Signed-off-by: Yonghong Song 
---
 tools/lib/bpf/libbpf.c   |  2 ++
 tools/lib/bpf/libbpf_errno.c | 10 ++
 2 files changed, 12 insertions(+)

diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c
index ed4212a4c5f9..59b748ebd15f 100644
--- a/tools/lib/bpf/libbpf.c
+++ b/tools/lib/bpf/libbpf.c
@@ -9,7 +9,9 @@
  * Copyright (C) 2017 Nicira, Inc.
  */
 
+#ifndef _GNU_SOURCE
 #define _GNU_SOURCE
+#endif
 #include 
 #include 
 #include 
diff --git a/tools/lib/bpf/libbpf_errno.c b/tools/lib/bpf/libbpf_errno.c
index d83b17f8435c..286e497c50ec 100644
--- a/tools/lib/bpf/libbpf_errno.c
+++ b/tools/lib/bpf/libbpf_errno.c
@@ -40,9 +40,19 @@ int libbpf_strerror(int err, char *buf, size_t size)
err = err > 0 ? err : -err;
 
if (err < __LIBBPF_ERRNO__START) {
+#ifdef _GNU_SOURCE
+   const char *ret_buf;
+#endif
int ret;
 
+#ifdef _GNU_SOURCE
+   ret_buf = strerror_r(err, buf, size);
+   if (ret_buf != buf)
+   snprintf(buf, size, "%s", ret_buf);
+   ret = 0;
+#else
ret = strerror_r(err, buf, size);
+#endif
buf[size - 1] = '\0';
return ret;
}
-- 
2.17.1



[PATCH bpf] tools: bpftool: fix a bitfield pretty print issue

2018-11-28 Thread Yonghong Song
Commit b12d6ec09730 ("bpf: btf: add btf print functionality")
added btf pretty print functionality to bpftool.
There is a problem though in printing a bitfield whose type
has modifiers.

For example, for a type like
  typedef int ___int;
  struct tmp_t {
  int a:3;
  ___int b:3;
  };
Suppose we have a map
  struct bpf_map_def SEC("maps") tmpmap = {
  .type = BPF_MAP_TYPE_HASH,
  .key_size = sizeof(__u32),
  .value_size = sizeof(struct tmp_t),
  .max_entries = 1,
  };
and the hash table is populated with one element with
key 0 and value (.a = 1 and .b = 2).

In BTF, the struct member "b" will have a type "typedef" which
points to an int type. The current implementation does not
pass the bit offset during transition from typedef to int type,
hence incorrectly print the value as
  $ bpftool m d id 79
  [{
  "key": 0,
  "value": {
  "a": 0x1,
  "b": 0x1
  }
  }
  ]

This patch fixed the issue by carrying bit_offset along the type
chain during bit_field print. The correct result can be printed as
  $ bpftool m d id 76
  [{
  "key": 0,
  "value": {
  "a": 0x1,
  "b": 0x2
  }
  }
  ]

The kernel pretty print is implemented correctly and does not
have this issue.

Fixes: b12d6ec09730 ("bpf: btf: add btf print functionality")
Signed-off-by: Yonghong Song 
---
 tools/bpf/bpftool/btf_dumper.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/tools/bpf/bpftool/btf_dumper.c b/tools/bpf/bpftool/btf_dumper.c
index 55bc512a1831..e4e6e2b3fd84 100644
--- a/tools/bpf/bpftool/btf_dumper.c
+++ b/tools/bpf/bpftool/btf_dumper.c
@@ -32,7 +32,7 @@ static void btf_dumper_ptr(const void *data, json_writer_t 
*jw,
 }
 
 static int btf_dumper_modifier(const struct btf_dumper *d, __u32 type_id,
-  const void *data)
+  __u8 bit_offset, const void *data)
 {
int actual_type_id;
 
@@ -40,7 +40,7 @@ static int btf_dumper_modifier(const struct btf_dumper *d, 
__u32 type_id,
if (actual_type_id < 0)
return actual_type_id;
 
-   return btf_dumper_do_type(d, actual_type_id, 0, data);
+   return btf_dumper_do_type(d, actual_type_id, bit_offset, data);
 }
 
 static void btf_dumper_enum(const void *data, json_writer_t *jw)
@@ -237,7 +237,7 @@ static int btf_dumper_do_type(const struct btf_dumper *d, 
__u32 type_id,
case BTF_KIND_VOLATILE:
case BTF_KIND_CONST:
case BTF_KIND_RESTRICT:
-   return btf_dumper_modifier(d, type_id, data);
+   return btf_dumper_modifier(d, type_id, bit_offset, data);
default:
jsonw_printf(d->jw, "(unsupported-kind");
return -EINVAL;
-- 
2.17.1



[PATCH bpf v2 1/4] bpf: btf: implement btf_name_valid_identifier()

2018-11-27 Thread Yonghong Song
Function btf_name_valid_identifier() have been implemented in
bpf-next commit 2667a2626f4d ("bpf: btf: Add BTF_KIND_FUNC and
BTF_KIND_FUNC_PROTO"). Backport this function so later patch
can use it.

Fixes: 69b693f0aefa ("bpf: btf: Introduce BPF Type Format (BTF)")
Signed-off-by: Yonghong Song 
---
 kernel/bpf/btf.c | 25 +
 1 file changed, 25 insertions(+)

diff --git a/kernel/bpf/btf.c b/kernel/bpf/btf.c
index ee4c82667d65..93c233ab2db6 100644
--- a/kernel/bpf/btf.c
+++ b/kernel/bpf/btf.c
@@ -5,6 +5,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -426,6 +427,30 @@ static bool btf_name_offset_valid(const struct btf *btf, 
u32 offset)
offset < btf->hdr.str_len;
 }
 
+/* Only C-style identifier is permitted. This can be relaxed if
+ * necessary.
+ */
+static bool btf_name_valid_identifier(const struct btf *btf, u32 offset)
+{
+   /* offset must be valid */
+   const char *src = >strings[offset];
+   const char *src_limit;
+
+   if (!isalpha(*src) && *src != '_')
+   return false;
+
+   /* set a limit on identifier length */
+   src_limit = src + KSYM_NAME_LEN;
+   src++;
+   while (*src && src < src_limit) {
+   if (!isalnum(*src) && *src != '_')
+   return false;
+   src++;
+   }
+
+   return !*src;
+}
+
 static const char *btf_name_by_offset(const struct btf *btf, u32 offset)
 {
if (!offset)
-- 
2.17.1



[PATCH bpf v2 3/4] tools/bpf: fix two test_btf unit test cases

2018-11-27 Thread Yonghong Song
From: Martin KaFai Lau 

There are two unit test cases, which should encode
TYPEDEF type, but instead encode PTR type.
The error is flagged out after enforcing name
checking in the previous patch.

Fixes: c0fa1b6c3efc ("bpf: btf: Add BTF tests")
Signed-off-by: Martin KaFai Lau 
Signed-off-by: Yonghong Song 
---
 tools/testing/selftests/bpf/test_btf.c | 14 +++---
 1 file changed, 7 insertions(+), 7 deletions(-)

diff --git a/tools/testing/selftests/bpf/test_btf.c 
b/tools/testing/selftests/bpf/test_btf.c
index f42b3396d622..b361bb851829 100644
--- a/tools/testing/selftests/bpf/test_btf.c
+++ b/tools/testing/selftests/bpf/test_btf.c
@@ -432,11 +432,11 @@ static struct btf_raw_test raw_tests[] = {
/* const void* */   /* [3] */
BTF_TYPE_ENC(0, BTF_INFO_ENC(BTF_KIND_PTR, 0, 0), 2),
/* typedef const void * const_void_ptr */
-   BTF_TYPE_ENC(NAME_TBD, BTF_INFO_ENC(BTF_KIND_PTR, 0, 0), 3),
-   /* struct A { *//* [4] */
+   BTF_TYPEDEF_ENC(NAME_TBD, 3),   /* [4] */
+   /* struct A { *//* [5] */
BTF_TYPE_ENC(NAME_TBD, BTF_INFO_ENC(BTF_KIND_STRUCT, 0, 1), 
sizeof(void *)),
/* const_void_ptr m; */
-   BTF_MEMBER_ENC(NAME_TBD, 3, 0),
+   BTF_MEMBER_ENC(NAME_TBD, 4, 0),
/* } */
BTF_END_RAW,
},
@@ -494,10 +494,10 @@ static struct btf_raw_test raw_tests[] = {
BTF_TYPE_ENC(0, BTF_INFO_ENC(BTF_KIND_CONST, 0, 0), 0),
/* const void* */   /* [3] */
BTF_TYPE_ENC(0, BTF_INFO_ENC(BTF_KIND_PTR, 0, 0), 2),
-   /* typedef const void * const_void_ptr */   /* [4] */
-   BTF_TYPE_ENC(NAME_TBD, BTF_INFO_ENC(BTF_KIND_PTR, 0, 0), 3),
-   /* const_void_ptr[4] */ /* [5] */
-   BTF_TYPE_ARRAY_ENC(3, 1, 4),
+   /* typedef const void * const_void_ptr */
+   BTF_TYPEDEF_ENC(NAME_TBD, 3),   /* [4] */
+   /* const_void_ptr[4] */
+   BTF_TYPE_ARRAY_ENC(4, 1, 4),/* [5] */
BTF_END_RAW,
},
.str_sec = "\0const_void_ptr",
-- 
2.17.1



[PATCH bpf v2 0/4] bpf: btf: check name validity for various types

2018-11-27 Thread Yonghong Song
This patch set added name checking for PTR, ARRAY, VOLATILE, TYPEDEF,
CONST, RESTRICT, STRUCT, UNION, ENUM and FWD types. Such a strict
name checking makes BTF more sound in the kernel and future
BTF-to-header-file converesion ([1]) less fragile.

Patch #1 implemented btf_name_valid_identifier() for name checking
which will be used in Patch #2.
Patch #2 checked name validity for the above mentioned types.
Patch #3 fixed two existing test_btf unit tests exposed by the strict
name checking.
Patch #4 added additional test cases.

This patch set is against bpf tree.

Patch #1 has been implemented in bpf-next commit
Commit 2667a2626f4d ("bpf: btf: Add BTF_KIND_FUNC
and BTF_KIND_FUNC_PROTO"), so there is no need to apply this
patch to bpf-next. In case this patch is applied to bpf-next,
there will be a minor conflict like
  diff --cc kernel/bpf/btf.c
  index a09b2f94ab25,93c233ab2db6..
  --- a/kernel/bpf/btf.c
  +++ b/kernel/bpf/btf.c
  @@@ -474,7 -451,7 +474,11 @@@ static bool btf_name_valid_identifier(c
  return !*src;
}

  ++<<<<<<< HEAD
   +const char *btf_name_by_offset(const struct btf *btf, u32 offset)
  ++===
  + static const char *btf_name_by_offset(const struct btf *btf, u32 offset)
  ++>>>>>>> fa9566b0847d... bpf: btf: implement btf_name_valid_identifier()
{
  if (!offset)
  return "(anon)";
Just resolve the conflict by taking the "const char ..." line.

Patches #2, #3 and #4 can be applied to bpf-next without conflict.

[1]: http://vger.kernel.org/lpc-bpf2018.html#session-2

Yonghong Song (4):
  bpf: btf: implement btf_name_valid_identifier()
  bpf: btf: check name validity for various types
  tools/bpf: fix two test_btf unit test cases
  tools/bpf: add addition type tests to test_btf

 kernel/bpf/btf.c   |  82 ++
 tools/testing/selftests/bpf/test_btf.c | 375 -
 2 files changed, 450 insertions(+), 7 deletions(-)

-- 
2.17.1



[PATCH bpf v2 4/4] tools/bpf: add addition type tests to test_btf

2018-11-27 Thread Yonghong Song
The following additional unit testcases are added to test_btf:
...
BTF raw test[42] (typedef (invalid name, name_off = 0)): OK
BTF raw test[43] (typedef (invalid name, invalid identifier)): OK
BTF raw test[44] (ptr type (invalid name, name_off <> 0)): OK
BTF raw test[45] (volatile type (invalid name, name_off <> 0)): OK
BTF raw test[46] (const type (invalid name, name_off <> 0)): OK
BTF raw test[47] (restrict type (invalid name, name_off <> 0)): OK
BTF raw test[48] (fwd type (invalid name, name_off = 0)): OK
BTF raw test[49] (fwd type (invalid name, invalid identifier)): OK
BTF raw test[50] (array type (invalid name, name_off <> 0)): OK
BTF raw test[51] (struct type (name_off = 0)): OK
BTF raw test[52] (struct type (invalid name, invalid identifier)): OK
BTF raw test[53] (struct member (name_off = 0)): OK
BTF raw test[54] (struct member (invalid name, invalid identifier)): OK
BTF raw test[55] (enum type (name_off = 0)): OK
BTF raw test[56] (enum type (invalid name, invalid identifier)): OK
BTF raw test[57] (enum member (invalid name, name_off = 0)): OK
BTF raw test[58] (enum member (invalid name, invalid identifier)): OK
...

Fixes: c0fa1b6c3efc ("bpf: btf: Add BTF tests")
Acked-by: Martin KaFai Lau 
Signed-off-by: Yonghong Song 
---
 tools/testing/selftests/bpf/test_btf.c | 361 +
 1 file changed, 361 insertions(+)

diff --git a/tools/testing/selftests/bpf/test_btf.c 
b/tools/testing/selftests/bpf/test_btf.c
index b361bb851829..38e1cbaaffdb 100644
--- a/tools/testing/selftests/bpf/test_btf.c
+++ b/tools/testing/selftests/bpf/test_btf.c
@@ -1292,6 +1292,367 @@ static struct btf_raw_test raw_tests[] = {
.err_str = "type != 0",
 },
 
+{
+   .descr = "typedef (invalid name, name_off = 0)",
+   .raw_types = {
+   BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4),  /* [1] */
+   BTF_TYPEDEF_ENC(0, 1),  /* [2] */
+   BTF_END_RAW,
+   },
+   .str_sec = "\0__int",
+   .str_sec_size = sizeof("\0__int"),
+   .map_type = BPF_MAP_TYPE_ARRAY,
+   .map_name = "typedef_check_btf",
+   .key_size = sizeof(int),
+   .value_size = sizeof(int),
+   .key_type_id = 1,
+   .value_type_id = 1,
+   .max_entries = 4,
+   .btf_load_err = true,
+   .err_str = "Invalid name",
+},
+
+{
+   .descr = "typedef (invalid name, invalid identifier)",
+   .raw_types = {
+   BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4),  /* [1] */
+   BTF_TYPEDEF_ENC(NAME_TBD, 1),   /* [2] */
+   BTF_END_RAW,
+   },
+   .str_sec = "\0__!int",
+   .str_sec_size = sizeof("\0__!int"),
+   .map_type = BPF_MAP_TYPE_ARRAY,
+   .map_name = "typedef_check_btf",
+   .key_size = sizeof(int),
+   .value_size = sizeof(int),
+   .key_type_id = 1,
+   .value_type_id = 1,
+   .max_entries = 4,
+   .btf_load_err = true,
+   .err_str = "Invalid name",
+},
+
+{
+   .descr = "ptr type (invalid name, name_off <> 0)",
+   .raw_types = {
+   BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4),  /* [1] 
*/
+   BTF_TYPE_ENC(NAME_TBD,
+BTF_INFO_ENC(BTF_KIND_PTR, 0, 0), 1),  /* [2] 
*/
+   BTF_END_RAW,
+   },
+   .str_sec = "\0__int",
+   .str_sec_size = sizeof("\0__int"),
+   .map_type = BPF_MAP_TYPE_ARRAY,
+   .map_name = "ptr_type_check_btf",
+   .key_size = sizeof(int),
+   .value_size = sizeof(int),
+   .key_type_id = 1,
+   .value_type_id = 1,
+   .max_entries = 4,
+   .btf_load_err = true,
+   .err_str = "Invalid name",
+},
+
+{
+   .descr = "volatile type (invalid name, name_off <> 0)",
+   .raw_types = {
+   BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4),  /* [1] 
*/
+   BTF_TYPE_ENC(NAME_TBD,
+BTF_INFO_ENC(BTF_KIND_VOLATILE, 0, 0), 1), /* [2] 
*/
+   BTF_END_RAW,
+   },
+   .str_sec = "\0__int",
+   .str_sec_size = sizeof("\0__int"),
+   .map_type = BPF_MAP_TYPE_ARRAY,
+   .map_name = "volatile_type_check_btf",
+   .key_size = sizeof(int),
+   .value_size = sizeof(int),
+   .key_type_id = 1,
+   .value_type_id = 1,
+   .max_entries = 4,
+   .btf_load_err = true,
+   .err_str = "Invalid name",
+},
+
+{
+   .descr = "const type (invalid name, name_off <> 0)",
+   .raw_types = {
+   BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4),  /* [1] 
*/
+   BTF_TYPE_ENC(NAME_TBD,
+BTF_INFO_ENC(BTF_KIND_CONST, 0, 0), 1),/* [2] 
*/
+  

[PATCH bpf v2 2/4] bpf: btf: check name validity for various types

2018-11-27 Thread Yonghong Song
This patch added name checking for the following types:
 . BTF_KIND_PTR, BTF_KIND_ARRAY, BTF_KIND_VOLATILE,
   BTF_KIND_CONST, BTF_KIND_RESTRICT:
 the name must be null
 . BTF_KIND_STRUCT, BTF_KIND_UNION: the struct/member name
 is either null or a valid identifier
 . BTF_KIND_ENUM: the enum type name is either null or a valid
 identifier; the enumerator name must be a valid identifier.
 . BTF_KIND_FWD: the name must be a valid identifier
 . BTF_KIND_TYPEDEF: the name must be a valid identifier

For those places a valid name is required, the name must be
a valid C identifier. This can be relaxed later if we found
use cases for a different (non-C) frontend.

Fixes: 69b693f0aefa ("bpf: btf: Introduce BPF Type Format (BTF)")
Acked-by: Martin KaFai Lau 
Signed-off-by: Yonghong Song 
---
 kernel/bpf/btf.c | 57 
 1 file changed, 57 insertions(+)

diff --git a/kernel/bpf/btf.c b/kernel/bpf/btf.c
index 93c233ab2db6..4da543d6bea2 100644
--- a/kernel/bpf/btf.c
+++ b/kernel/bpf/btf.c
@@ -1168,6 +1168,22 @@ static int btf_ref_type_check_meta(struct 
btf_verifier_env *env,
return -EINVAL;
}
 
+   /* typedef type must have a valid name, and other ref types,
+* volatile, const, restrict, should have a null name.
+*/
+   if (BTF_INFO_KIND(t->info) == BTF_KIND_TYPEDEF) {
+   if (!t->name_off ||
+   !btf_name_valid_identifier(env->btf, t->name_off)) {
+   btf_verifier_log_type(env, t, "Invalid name");
+   return -EINVAL;
+   }
+   } else {
+   if (t->name_off) {
+   btf_verifier_log_type(env, t, "Invalid name");
+   return -EINVAL;
+   }
+   }
+
btf_verifier_log_type(env, t, NULL);
 
return 0;
@@ -1325,6 +1341,13 @@ static s32 btf_fwd_check_meta(struct btf_verifier_env 
*env,
return -EINVAL;
}
 
+   /* fwd type must have a valid name */
+   if (!t->name_off ||
+   !btf_name_valid_identifier(env->btf, t->name_off)) {
+   btf_verifier_log_type(env, t, "Invalid name");
+   return -EINVAL;
+   }
+
btf_verifier_log_type(env, t, NULL);
 
return 0;
@@ -1381,6 +1404,12 @@ static s32 btf_array_check_meta(struct btf_verifier_env 
*env,
return -EINVAL;
}
 
+   /* array type should not have a name */
+   if (t->name_off) {
+   btf_verifier_log_type(env, t, "Invalid name");
+   return -EINVAL;
+   }
+
if (btf_type_vlen(t)) {
btf_verifier_log_type(env, t, "vlen != 0");
return -EINVAL;
@@ -1557,6 +1586,13 @@ static s32 btf_struct_check_meta(struct btf_verifier_env 
*env,
return -EINVAL;
}
 
+   /* struct type either no name or a valid one */
+   if (t->name_off &&
+   !btf_name_valid_identifier(env->btf, t->name_off)) {
+   btf_verifier_log_type(env, t, "Invalid name");
+   return -EINVAL;
+   }
+
btf_verifier_log_type(env, t, NULL);
 
last_offset = 0;
@@ -1568,6 +1604,12 @@ static s32 btf_struct_check_meta(struct btf_verifier_env 
*env,
return -EINVAL;
}
 
+   /* struct member either no name or a valid one */
+   if (member->name_off &&
+   !btf_name_valid_identifier(btf, member->name_off)) {
+   btf_verifier_log_member(env, t, member, "Invalid name");
+   return -EINVAL;
+   }
/* A member cannot be in type void */
if (!member->type || !BTF_TYPE_ID_VALID(member->type)) {
btf_verifier_log_member(env, t, member,
@@ -1755,6 +1797,13 @@ static s32 btf_enum_check_meta(struct btf_verifier_env 
*env,
return -EINVAL;
}
 
+   /* enum type either no name or a valid one */
+   if (t->name_off &&
+   !btf_name_valid_identifier(env->btf, t->name_off)) {
+   btf_verifier_log_type(env, t, "Invalid name");
+   return -EINVAL;
+   }
+
btf_verifier_log_type(env, t, NULL);
 
for (i = 0; i < nr_enums; i++) {
@@ -1764,6 +1813,14 @@ static s32 btf_enum_check_meta(struct btf_verifier_env 
*env,
return -EINVAL;
}
 
+   /* enum member must have a valid name */
+   if (!enums[i].name_off ||
+   !btf_name_valid_identifier(btf, enums[i].name_off)) {
+   btf_verifier_log_type(env, t, "Invalid name");
+   return -EINVAL;
+   }
+
+
btf_verifier_log(env, "\t%s val=%d\n",
 btf_name_by_offset(btf, enums[i].name_off),
 enums[i].val);
-- 
2.17.1



Re: [PATCH bpf-next 1/3] bpf: btf: check name validity for various types

2018-11-27 Thread Yonghong Song


On 11/27/18 11:02 AM, Alexei Starovoitov wrote:
> On Mon, Nov 26, 2018 at 09:17:13PM -0800, Yonghong Song wrote:
>> Commit 2667a2626f4d ("bpf: btf: Add BTF_KIND_FUNC
>> and BTF_KIND_FUNC_PROTO") checked the name validity
>> for BTF_KIND_FUNC/BTF_KIND_FUNC_PROTO types such that:
>>   . BTF_KIND_FUNC must have a valid identifier name
>>   . BTF_KIND_PROTO must have a null name
>>   . The argument name of BTF_KIND_FUNC/BTF_KIND_FUNC_PROTO,
>> if not null, must be a valid identifier.
>>
>> This patch added name checking for the following types:
>>   . BTF_KIND_PTR, BTF_KIND_ARRAY, BTF_KIND_VOLATILE,
>> BTF_KIND_CONST, BTF_KIND_RESTRICT:
>>   the name must be null
>>   . BTF_KIND_STRUCT, BTF_KIND_UNION: the struct/member name
>>   is either null or a valid identifier
>>   . BTF_KIND_ENUM: the enum type name is either null or a valid
>>   identifier; the enumerator name must be a valid identifier.
>>   . BTF_KIND_FWD: the name must be a valid identifier
>>   . BTF_KIND_TYPEDEF: the name must be a valid identifier
>>
>> For those places a valid name is required, the name must be
>> a valid C identifier. This can be relaxed later if we found
>> use cases for a different (non-C) frontend.
>>
>> Acked-by: Martin KaFai Lau 
>> Signed-off-by: Yonghong Song 
> ...
>>  return 0;
>> @@ -1409,6 +1432,12 @@ static s32 btf_array_check_meta(struct 
>> btf_verifier_env *env,
>>  return -EINVAL;
>>  }
>>   
>> +/* array type should not have a name */
>> +if (t->name_off) {
>> +btf_verifier_log_type(env, t, "Invalid name");
>> +return -EINVAL;
>> +}
>> +
>>  if (btf_type_vlen(t)) {
>>  btf_verifier_log_type(env, t, "vlen != 0");
>>  return -EINVAL;
>> @@ -1585,6 +1614,13 @@ static s32 btf_struct_check_meta(struct 
>> btf_verifier_env *env,
>>  return -EINVAL;
>>  }
>>   
>> +/* struct type either no name or a valid one */
>> +if (t->name_off &&
>> +!btf_name_valid_identifier(env->btf, t->name_off)) {
> 
> Looks like some of these changes need to go into bpf tree.
> please split it up and let's try to minimize the conflicts between bpf and 
> bpf-next

Make sense. Will restructure and resubmit for bpf in the next version.

> Thanks!
> 


Re: [PATCH] selftests/bpf: add config fragment CONFIG_FTRACE_SYSCALLS

2018-11-27 Thread Yonghong Song


On 11/27/18 7:24 AM, Naresh Kamboju wrote:
> CONFIG_FTRACE_SYSCALLS=y is required for get_cgroup_id_user test case
> this test reads a file from debug trace path
> /sys/kernel/debug/tracing/events/syscalls/sys_enter_nanosleep/id
> 
> Signed-off-by: Naresh Kamboju 

Acked-by: Yonghong Song 

> ---
>   tools/testing/selftests/bpf/config | 1 +
>   1 file changed, 1 insertion(+)
> 
> diff --git a/tools/testing/selftests/bpf/config 
> b/tools/testing/selftests/bpf/config
> index 7f90d3645af8..37f947ec44ed 100644
> --- a/tools/testing/selftests/bpf/config
> +++ b/tools/testing/selftests/bpf/config
> @@ -22,3 +22,4 @@ CONFIG_NET_CLS_FLOWER=m
>   CONFIG_LWTUNNEL=y
>   CONFIG_BPF_STREAM_PARSER=y
>   CONFIG_XDP_SOCKETS=y
> +CONFIG_FTRACE_SYSCALLS=y
> 


[PATCH bpf-next 1/3] bpf: btf: check name validity for various types

2018-11-26 Thread Yonghong Song
Commit 2667a2626f4d ("bpf: btf: Add BTF_KIND_FUNC
and BTF_KIND_FUNC_PROTO") checked the name validity
for BTF_KIND_FUNC/BTF_KIND_FUNC_PROTO types such that:
 . BTF_KIND_FUNC must have a valid identifier name
 . BTF_KIND_PROTO must have a null name
 . The argument name of BTF_KIND_FUNC/BTF_KIND_FUNC_PROTO,
   if not null, must be a valid identifier.

This patch added name checking for the following types:
 . BTF_KIND_PTR, BTF_KIND_ARRAY, BTF_KIND_VOLATILE,
   BTF_KIND_CONST, BTF_KIND_RESTRICT:
 the name must be null
 . BTF_KIND_STRUCT, BTF_KIND_UNION: the struct/member name
 is either null or a valid identifier
 . BTF_KIND_ENUM: the enum type name is either null or a valid
 identifier; the enumerator name must be a valid identifier.
 . BTF_KIND_FWD: the name must be a valid identifier
 . BTF_KIND_TYPEDEF: the name must be a valid identifier

For those places a valid name is required, the name must be
a valid C identifier. This can be relaxed later if we found
use cases for a different (non-C) frontend.

Acked-by: Martin KaFai Lau 
Signed-off-by: Yonghong Song 
---
 kernel/bpf/btf.c | 57 
 1 file changed, 57 insertions(+)

diff --git a/kernel/bpf/btf.c b/kernel/bpf/btf.c
index a09b2f94ab25..793acba40b4c 100644
--- a/kernel/bpf/btf.c
+++ b/kernel/bpf/btf.c
@@ -1195,6 +1195,22 @@ static int btf_ref_type_check_meta(struct 
btf_verifier_env *env,
return -EINVAL;
}
 
+   /* typedef type must have a valid name, and other ref types,
+* volatile, const, restrict, should have a null name.
+*/
+   if (BTF_INFO_KIND(t->info) == BTF_KIND_TYPEDEF) {
+   if (!t->name_off ||
+   !btf_name_valid_identifier(env->btf, t->name_off)) {
+   btf_verifier_log_type(env, t, "Invalid name");
+   return -EINVAL;
+   }
+   } else {
+   if (t->name_off) {
+   btf_verifier_log_type(env, t, "Invalid name");
+   return -EINVAL;
+   }
+   }
+
btf_verifier_log_type(env, t, NULL);
 
return 0;
@@ -1353,6 +1369,13 @@ static s32 btf_fwd_check_meta(struct btf_verifier_env 
*env,
return -EINVAL;
}
 
+   /* fwd type must have a valid name */
+   if (!t->name_off ||
+   !btf_name_valid_identifier(env->btf, t->name_off)) {
+   btf_verifier_log_type(env, t, "Invalid name");
+   return -EINVAL;
+   }
+
btf_verifier_log_type(env, t, NULL);
 
return 0;
@@ -1409,6 +1432,12 @@ static s32 btf_array_check_meta(struct btf_verifier_env 
*env,
return -EINVAL;
}
 
+   /* array type should not have a name */
+   if (t->name_off) {
+   btf_verifier_log_type(env, t, "Invalid name");
+   return -EINVAL;
+   }
+
if (btf_type_vlen(t)) {
btf_verifier_log_type(env, t, "vlen != 0");
return -EINVAL;
@@ -1585,6 +1614,13 @@ static s32 btf_struct_check_meta(struct btf_verifier_env 
*env,
return -EINVAL;
}
 
+   /* struct type either no name or a valid one */
+   if (t->name_off &&
+   !btf_name_valid_identifier(env->btf, t->name_off)) {
+   btf_verifier_log_type(env, t, "Invalid name");
+   return -EINVAL;
+   }
+
btf_verifier_log_type(env, t, NULL);
 
last_offset = 0;
@@ -1596,6 +1632,12 @@ static s32 btf_struct_check_meta(struct btf_verifier_env 
*env,
return -EINVAL;
}
 
+   /* struct member either no name or a valid one */
+   if (member->name_off &&
+   !btf_name_valid_identifier(btf, member->name_off)) {
+   btf_verifier_log_member(env, t, member, "Invalid name");
+   return -EINVAL;
+   }
/* A member cannot be in type void */
if (!member->type || !BTF_TYPE_ID_VALID(member->type)) {
btf_verifier_log_member(env, t, member,
@@ -1783,6 +1825,13 @@ static s32 btf_enum_check_meta(struct btf_verifier_env 
*env,
return -EINVAL;
}
 
+   /* enum type either no name or a valid one */
+   if (t->name_off &&
+   !btf_name_valid_identifier(env->btf, t->name_off)) {
+   btf_verifier_log_type(env, t, "Invalid name");
+   return -EINVAL;
+   }
+
btf_verifier_log_type(env, t, NULL);
 
for (i = 0; i < nr_enums; i++) {
@@ -1792,6 +1841,14 @@ static s32 btf_enum_check_meta(struct btf_verifier_env 
*env,
return -EINVAL;
}
 
+   /* enum member must have a valid na

[PATCH bpf-next 2/3] tools/bpf: fix two test_btf unit test cases

2018-11-26 Thread Yonghong Song
From: Martin KaFai Lau 

There are two unit test cases, which should encode
TYPEDEF type, but instead encode PTR type.
The error is flagged out after enforcing name
checking in the previous patch.

Fixes: c0fa1b6c3efc ("bpf: btf: Add BTF tests")
Signed-off-by: Martin KaFai Lau 
Signed-off-by: Yonghong Song 
---
 tools/testing/selftests/bpf/test_btf.c | 18 +-
 1 file changed, 9 insertions(+), 9 deletions(-)

diff --git a/tools/testing/selftests/bpf/test_btf.c 
b/tools/testing/selftests/bpf/test_btf.c
index bae7308b7ec5..99a92923e3f9 100644
--- a/tools/testing/selftests/bpf/test_btf.c
+++ b/tools/testing/selftests/bpf/test_btf.c
@@ -447,13 +447,13 @@ static struct btf_raw_test raw_tests[] = {
/* const void *//* [2] */
BTF_TYPE_ENC(0, BTF_INFO_ENC(BTF_KIND_CONST, 0, 0), 0),
/* const void* */   /* [3] */
-   BTF_TYPE_ENC(0, BTF_INFO_ENC(BTF_KIND_PTR, 0, 0), 2),
+   BTF_PTR_ENC(2),
/* typedef const void * const_void_ptr */
-   BTF_TYPE_ENC(NAME_TBD, BTF_INFO_ENC(BTF_KIND_PTR, 0, 0), 3),
-   /* struct A { *//* [4] */
+   BTF_TYPEDEF_ENC(NAME_TBD, 3),   /* [4] */
+   /* struct A { *//* [5] */
BTF_TYPE_ENC(NAME_TBD, BTF_INFO_ENC(BTF_KIND_STRUCT, 0, 1), 
sizeof(void *)),
/* const_void_ptr m; */
-   BTF_MEMBER_ENC(NAME_TBD, 3, 0),
+   BTF_MEMBER_ENC(NAME_TBD, 4, 0),
/* } */
BTF_END_RAW,
},
@@ -510,11 +510,11 @@ static struct btf_raw_test raw_tests[] = {
/* const void *//* [2] */
BTF_TYPE_ENC(0, BTF_INFO_ENC(BTF_KIND_CONST, 0, 0), 0),
/* const void* */   /* [3] */
-   BTF_TYPE_ENC(0, BTF_INFO_ENC(BTF_KIND_PTR, 0, 0), 2),
-   /* typedef const void * const_void_ptr */   /* [4] */
-   BTF_TYPE_ENC(NAME_TBD, BTF_INFO_ENC(BTF_KIND_PTR, 0, 0), 3),
-   /* const_void_ptr[4] */ /* [5] */
-   BTF_TYPE_ARRAY_ENC(3, 1, 4),
+   BTF_PTR_ENC(2),
+   /* typedef const void * const_void_ptr */
+   BTF_TYPEDEF_ENC(NAME_TBD, 3),   /* [4] */
+   /* const_void_ptr[4] */
+   BTF_TYPE_ARRAY_ENC(4, 1, 4),/* [5] */
BTF_END_RAW,
},
.str_sec = "\0const_void_ptr",
-- 
2.17.1



[PATCH bpf-next 3/3] tools/bpf: add addition type tests to test_btf

2018-11-26 Thread Yonghong Song
The following additional unit testcases are added to test_btf:
  BTF raw test[65] (typedef (invalid name, name_off = 0)): OK
  BTF raw test[66] (typedef (invalid name, invalid identifier)): OK
  BTF raw test[67] (ptr type (invalid name, name_off <> 0)): OK
  BTF raw test[68] (volatile type (invalid name, name_off <> 0)): OK
  BTF raw test[69] (const type (invalid name, name_off <> 0)): OK
  BTF raw test[70] (restrict type (invalid name, name_off <> 0)): OK
  BTF raw test[71] (fwd type (invalid name, name_off = 0)): OK
  BTF raw test[72] (fwd type (invalid name, invalid identifier)): OK
  BTF raw test[73] (array type (invalid name, name_off <> 0)): OK
  BTF raw test[74] (struct type (name_off = 0)): OK
  BTF raw test[75] (struct type (invalid name, invalid identifier)): OK
  BTF raw test[76] (struct member (name_off = 0)): OK
  BTF raw test[77] (struct member (invalid name, invalid identifier)): OK
  BTF raw test[78] (enum type (name_off = 0)): OK
  BTF raw test[79] (enum type (invalid name, invalid identifier)): OK
  BTF raw test[80] (enum member (invalid name, name_off = 0)): OK
  BTF raw test[81] (enum member (invalid name, invalid identifier)): OK

Acked-by: Martin KaFai Lau 
Signed-off-by: Yonghong Song 
---
 tools/testing/selftests/bpf/test_btf.c | 362 +
 1 file changed, 362 insertions(+)

diff --git a/tools/testing/selftests/bpf/test_btf.c 
b/tools/testing/selftests/bpf/test_btf.c
index 99a92923e3f9..a7267815311f 100644
--- a/tools/testing/selftests/bpf/test_btf.c
+++ b/tools/testing/selftests/bpf/test_btf.c
@@ -1849,6 +1849,368 @@ static struct btf_raw_test raw_tests[] = {
.err_str = "Invalid type_id",
 },
 
+{
+   .descr = "typedef (invalid name, name_off = 0)",
+   .raw_types = {
+   BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4),  /* [1] */
+   BTF_TYPEDEF_ENC(0, 1),  /* [2] */
+   BTF_END_RAW,
+   },
+   .str_sec = "\0__int",
+   .str_sec_size = sizeof("\0__int"),
+   .map_type = BPF_MAP_TYPE_ARRAY,
+   .map_name = "typedef_check_btf",
+   .key_size = sizeof(int),
+   .value_size = sizeof(int),
+   .key_type_id = 1,
+   .value_type_id = 1,
+   .max_entries = 4,
+   .btf_load_err = true,
+   .err_str = "Invalid name",
+},
+
+{
+   .descr = "typedef (invalid name, invalid identifier)",
+   .raw_types = {
+   BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4),  /* [1] */
+   BTF_TYPEDEF_ENC(NAME_TBD, 1),   /* [2] */
+   BTF_END_RAW,
+   },
+   .str_sec = "\0__!int",
+   .str_sec_size = sizeof("\0__!int"),
+   .map_type = BPF_MAP_TYPE_ARRAY,
+   .map_name = "typedef_check_btf",
+   .key_size = sizeof(int),
+   .value_size = sizeof(int),
+   .key_type_id = 1,
+   .value_type_id = 1,
+   .max_entries = 4,
+   .btf_load_err = true,
+   .err_str = "Invalid name",
+},
+
+{
+   .descr = "ptr type (invalid name, name_off <> 0)",
+   .raw_types = {
+   BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4),  /* [1] 
*/
+   BTF_TYPE_ENC(NAME_TBD,
+BTF_INFO_ENC(BTF_KIND_PTR, 0, 0), 1),  /* [2] 
*/
+   BTF_END_RAW,
+   },
+   .str_sec = "\0__int",
+   .str_sec_size = sizeof("\0__int"),
+   .map_type = BPF_MAP_TYPE_ARRAY,
+   .map_name = "ptr_type_check_btf",
+   .key_size = sizeof(int),
+   .value_size = sizeof(int),
+   .key_type_id = 1,
+   .value_type_id = 1,
+   .max_entries = 4,
+   .btf_load_err = true,
+   .err_str = "Invalid name",
+},
+
+{
+   .descr = "volatile type (invalid name, name_off <> 0)",
+   .raw_types = {
+   BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4),  /* [1] 
*/
+   BTF_TYPE_ENC(NAME_TBD,
+BTF_INFO_ENC(BTF_KIND_VOLATILE, 0, 0), 1), /* [2] 
*/
+   BTF_END_RAW,
+   },
+   .str_sec = "\0__int",
+   .str_sec_size = sizeof("\0__int"),
+   .map_type = BPF_MAP_TYPE_ARRAY,
+   .map_name = "volatile_type_check_btf",
+   .key_size = sizeof(int),
+   .value_size = sizeof(int),
+   .key_type_id = 1,
+   .value_type_id = 1,
+   .max_entries = 4,
+   .btf_load_err = true,
+   .err_str = "Invalid name",
+},
+
+{
+   .descr = "const type (invalid name, name_off <> 0)",
+   .raw_types = {
+   BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4),  /* [1] 
*/
+   BTF_TYPE_ENC(NAME_TBD,
+BTF_INFO_ENC(BTF_KIND_CONST, 0, 0), 1),/* [2] 
*/
+   BTF_END_RAW,
+   },
+   .

[PATCH bpf-next 0/3] bpf: btf: check name validity for various types

2018-11-26 Thread Yonghong Song
Commit 2667a2626f4d ("bpf: btf: Add BTF_KIND_FUNC
and BTF_KIND_FUNC_PROTO") checked the name validity
for BTF_KIND_FUNC/FUNC_PROTO types.

This patch added name checking for PTR, ARRAY, VOLATILE, TYPEDEF,
CONST, RESTRICT, STRUCT, UNION, ENUM and FWD types. Such a strict
name checking makes BTF more sound in the kernel and future
BTF-to-header-file converesion ([1]) less fragile.

[1]: http://vger.kernel.org/lpc-bpf2018.html#session-2

Yonghong Song (3):
  bpf: btf: check name validity for various types
  tools/bpf: fix two test_btf unit test cases
  tools/bpf: add addition type tests to test_btf

 kernel/bpf/btf.c   |  57 
 tools/testing/selftests/bpf/test_btf.c | 380 -
 2 files changed, 428 insertions(+), 9 deletions(-)

-- 
2.17.1



[PATCH bpf-next 0/2] bpf: support proper non-jit func info

2018-11-24 Thread Yonghong Song
Commit 838e96904ff3 ("bpf: Introduce bpf_func_info")
added bpf func info support. The userspace is able
to get better ksym's for bpf programs with jit, and
is able to print out func prototypes.

For a program containing func-to-func calls, the existing
implementation returns user specified number of function
calls and BTF types if jit is enabled. If the jit is not
enabled, it only returns the type for the main function.

This is undesirable. Interpreter may still be used
and we should keep feature identical regardless of
whether jit is enabled or not.
This patch fixed this discrepancy.

The following example shows bpftool output for
the bpf program in selftests test_btf_haskv.o when jit
is disabled:
  $ bpftool prog dump xlated id 1490
  int _dummy_tracepoint(struct dummy_tracepoint_args * arg):
 0: (85) call pc+2#__bpf_prog_run_args32
 1: (b7) r0 = 0
 2: (95) exit
  int test_long_fname_1(struct dummy_tracepoint_args * arg):
 3: (85) call pc+1#__bpf_prog_run_args32
 4: (95) exit
  int test_long_fname_2(struct dummy_tracepoint_args * arg):
 5: (b7) r2 = 0
 6: (63) *(u32 *)(r10 -4) = r2
 7: (79) r1 = *(u64 *)(r1 +8)
 8: (15) if r1 == 0x0 goto pc+9
 9: (bf) r2 = r10
10: (07) r2 += -4
11: (18) r1 = map[id:1173]
13: (85) call bpf_map_lookup_elem#77088
14: (15) if r0 == 0x0 goto pc+3
15: (61) r1 = *(u32 *)(r0 +4)
16: (07) r1 += 1
17: (63) *(u32 *)(r0 +4) = r1
18: (95) exit
  $ bpftool prog dump jited id 1490
no instructions returned

Yonghong Song (2):
  bpf: btf: support proper non-jit func info
  tools/bpf: change selftest test_btf for both jit and non-jit

 include/linux/bpf.h|  6 ++-
 include/linux/bpf_verifier.h   |  1 -
 kernel/bpf/core.c  |  3 +-
 kernel/bpf/syscall.c   | 33 
 kernel/bpf/verifier.c  | 55 ++
 tools/testing/selftests/bpf/test_btf.c | 33 ++--
 6 files changed, 55 insertions(+), 76 deletions(-)

-- 
2.17.1



[PATCH bpf-next 1/2] bpf: btf: support proper non-jit func info

2018-11-24 Thread Yonghong Song
Commit 838e96904ff3 ("bpf: Introduce bpf_func_info")
added bpf func info support. The userspace is able
to get better ksym's for bpf programs with jit, and
is able to print out func prototypes.

For a program containing func-to-func calls, the existing
implementation returns user specified number of function
calls and BTF types if jit is enabled. If the jit is not
enabled, it only returns the type for the main function.

This is undesirable. Interpreter may still be used
and we should keep feature identical regardless of
whether jit is enabled or not.
This patch fixed this discrepancy.

Fixes: 838e96904ff3 ("bpf: Introduce bpf_func_info")
Signed-off-by: Yonghong Song 
---
 include/linux/bpf.h  |  6 ++--
 include/linux/bpf_verifier.h |  1 -
 kernel/bpf/core.c|  3 +-
 kernel/bpf/syscall.c | 33 ++
 kernel/bpf/verifier.c| 55 +---
 5 files changed, 52 insertions(+), 46 deletions(-)

diff --git a/include/linux/bpf.h b/include/linux/bpf.h
index 7f0e225bf630..e82b7039fc66 100644
--- a/include/linux/bpf.h
+++ b/include/linux/bpf.h
@@ -299,7 +299,8 @@ struct bpf_prog_aux {
u32 max_pkt_offset;
u32 stack_depth;
u32 id;
-   u32 func_cnt;
+   u32 func_cnt; /* used by non-func prog as the number of func progs */
+   u32 func_idx; /* 0 for non-func prog, the index in func array for func 
prog */
bool offload_requested;
struct bpf_prog **func;
void *jit_data; /* JIT specific data. arch dependent */
@@ -317,7 +318,8 @@ struct bpf_prog_aux {
 #endif
struct bpf_prog_offload *offload;
struct btf *btf;
-   u32 type_id; /* type id for this prog/func */
+   struct bpf_func_info *func_info;
+   u32 func_info_cnt;
union {
struct work_struct work;
struct rcu_head rcu;
diff --git a/include/linux/bpf_verifier.h b/include/linux/bpf_verifier.h
index 204382f46fd8..11f5df1092d9 100644
--- a/include/linux/bpf_verifier.h
+++ b/include/linux/bpf_verifier.h
@@ -204,7 +204,6 @@ static inline bool bpf_verifier_log_needed(const struct 
bpf_verifier_log *log)
 struct bpf_subprog_info {
u32 start; /* insn idx of function entry point */
u16 stack_depth; /* max. stack depth used by this function */
-   u32 type_id; /* btf type_id for this subprog */
 };
 
 /* single container for all structs
diff --git a/kernel/bpf/core.c b/kernel/bpf/core.c
index 16d77012ad3e..002d67c62c8b 100644
--- a/kernel/bpf/core.c
+++ b/kernel/bpf/core.c
@@ -411,7 +411,8 @@ static void bpf_get_prog_name(const struct bpf_prog *prog, 
char *sym)
 
/* prog->aux->name will be ignored if full btf name is available */
if (prog->aux->btf) {
-   type = btf_type_by_id(prog->aux->btf, prog->aux->type_id);
+   type = btf_type_by_id(prog->aux->btf,
+ 
prog->aux->func_info[prog->aux->func_idx].type_id);
func_name = btf_name_by_offset(prog->aux->btf, type->name_off);
snprintf(sym, (size_t)(end - sym), "_%s", func_name);
return;
diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c
index 998377808102..85cbeec06e50 100644
--- a/kernel/bpf/syscall.c
+++ b/kernel/bpf/syscall.c
@@ -1214,6 +1214,7 @@ static void __bpf_prog_put(struct bpf_prog *prog, bool 
do_idr_lock)
bpf_prog_free_id(prog, do_idr_lock);
bpf_prog_kallsyms_del_all(prog);
btf_put(prog->aux->btf);
+   kvfree(prog->aux->func_info);
 
call_rcu(>aux->rcu, __bpf_prog_put_rcu);
}
@@ -2219,46 +2220,28 @@ static int bpf_prog_get_info_by_fd(struct bpf_prog 
*prog,
}
 
if (prog->aux->btf) {
+   u32 krec_size = sizeof(struct bpf_func_info);
u32 ucnt, urec_size;
 
info.btf_id = btf_id(prog->aux->btf);
 
ucnt = info.func_info_cnt;
-   info.func_info_cnt = prog->aux->func_cnt ? : 1;
+   info.func_info_cnt = prog->aux->func_info_cnt;
urec_size = info.func_info_rec_size;
-   info.func_info_rec_size = sizeof(struct bpf_func_info);
+   info.func_info_rec_size = krec_size;
if (ucnt) {
/* expect passed-in urec_size is what the kernel 
expects */
if (urec_size != info.func_info_rec_size)
return -EINVAL;
 
if (bpf_dump_raw_ok()) {
-   struct bpf_func_info kern_finfo;
char __user *user_finfo;
-   u32 i, insn_offset;
 
user_finfo = u64_to_user_ptr(info.func_info);
-  

[PATCH bpf-next 2/2] tools/bpf: change selftest test_btf for both jit and non-jit

2018-11-24 Thread Yonghong Song
The selftest test_btf is changed to test both jit and non-jit.
The test result should be the same regardless of whether jit
is enabled or not.

Signed-off-by: Yonghong Song 
---
 tools/testing/selftests/bpf/test_btf.c | 33 +++---
 1 file changed, 3 insertions(+), 30 deletions(-)

diff --git a/tools/testing/selftests/bpf/test_btf.c 
b/tools/testing/selftests/bpf/test_btf.c
index bcbda7037840..b4c8725b3004 100644
--- a/tools/testing/selftests/bpf/test_btf.c
+++ b/tools/testing/selftests/bpf/test_btf.c
@@ -29,7 +29,6 @@
 static uint32_t pass_cnt;
 static uint32_t error_cnt;
 static uint32_t skip_cnt;
-static bool jit_enabled;
 
 #define CHECK(condition, format...) ({ \
int __ret = !!(condition);  \
@@ -65,24 +64,6 @@ static int __base_pr(const char *format, ...)
return err;
 }
 
-static bool is_jit_enabled(void)
-{
-   const char *jit_sysctl = "/proc/sys/net/core/bpf_jit_enable";
-   bool enabled = false;
-   int sysctl_fd;
-
-   sysctl_fd = open(jit_sysctl, 0, O_RDONLY);
-   if (sysctl_fd != -1) {
-   char tmpc;
-
-   if (read(sysctl_fd, , sizeof(tmpc)) == 1)
-   enabled = (tmpc != '0');
-   close(sysctl_fd);
-   }
-
-   return enabled;
-}
-
 #define BTF_INFO_ENC(kind, root, vlen) \
((!!(root) << 31) | ((kind) << 24) | ((vlen) & BTF_MAX_VLEN))
 
@@ -2547,8 +2528,8 @@ static int do_test_file(unsigned int test_num)
  test->btf_kv_notfound))
goto done;
 
-   if (!jit_enabled || !has_btf_ext)
-   goto skip_jit;
+   if (!has_btf_ext)
+   goto skip;
 
/* get necessary program info */
info_len = sizeof(struct bpf_prog_info);
@@ -2636,7 +2617,7 @@ static int do_test_file(unsigned int test_num)
finfo = (void *)finfo + rec_size;
}
 
-skip_jit:
+skip:
fprintf(stderr, "OK");
 
 done:
@@ -3270,12 +3251,6 @@ static int do_test_func_type(int test_num)
err = -1;
goto done;
}
-   if (!jit_enabled) {
-   skip_cnt++;
-   fprintf(stderr, "SKIPPED, please enable sysctl 
bpf_jit_enable\n");
-   err = 0;
-   goto done;
-   }
 
/* get necessary lens */
info_len = sizeof(struct bpf_prog_info);
@@ -3452,8 +3427,6 @@ int main(int argc, char **argv)
if (args.always_log)
libbpf_set_print(__base_pr, __base_pr, __base_pr);
 
-   jit_enabled = is_jit_enabled();
-
if (args.raw_test)
err |= test_raw();
 
-- 
2.17.1



Re: [PATCH bpf-next 1/2] libbpf: Add version script for DSO

2018-11-21 Thread Yonghong Song


On 11/21/18 9:40 AM, Andrey Ignatov wrote:
> More and more projects use libbpf and one day it'll likely be packaged
> and distributed as DSO and that requires ABI versioning so that both
> compatible and incompatible changes to ABI can be introduced in a safe
> way in the future without breaking executables dynamically linked with a
> previous version of the library.
> 
> Usual way to do ABI versioning is version script for the linker. Add
> such a script for libbpf. All global symbols currently exported via
> LIBBPF_API macro are added to the version script libbpf.map.
> 
> The version name LIBBPF_0.0.1 is constructed from the name of the
> library + version specified by $(LIBBPF_VERSION) in Makefile.
> 
> Version script does not duplicate the work done by LIBBPF_API macro, it
> rather complements it. The macro is used at compile time and can be used
> by compiler to do optimization that can't be done at link time, it is
> purely about global symbol visibility. The version script, in turn, is
> used at link time and takes care of ABI versioning. Both techniques are
> described in details in [1].
> 
> Whenever ABI is changed in the future, version script should be changed
> appropriately.

Maybe we should clarify the policy of how version numbers should be 
change? Each commit which changes default global symbol ABI? Each kernel 
release?

> 
> [1] https://www.akkadia.org/drepper/dsohowto.pdf
> 
> Signed-off-by: Andrey Ignatov 
> ---
>   tools/lib/bpf/Makefile   |   4 +-
>   tools/lib/bpf/libbpf.map | 120 +++
>   2 files changed, 123 insertions(+), 1 deletion(-)
>   create mode 100644 tools/lib/bpf/libbpf.map
> 
> diff --git a/tools/lib/bpf/Makefile b/tools/lib/bpf/Makefile
> index 425b480bda75..d76c41fa2d39 100644
> --- a/tools/lib/bpf/Makefile
> +++ b/tools/lib/bpf/Makefile
> @@ -145,6 +145,7 @@ include $(srctree)/tools/build/Makefile.include
>   
>   BPF_IN:= $(OUTPUT)libbpf-in.o
>   LIB_FILE := $(addprefix $(OUTPUT),$(LIB_FILE))
> +VERSION_SCRIPT := libbpf.map
>   
>   CMD_TARGETS = $(LIB_FILE)
>   
> @@ -170,7 +171,8 @@ $(BPF_IN): force elfdep bpfdep
>   $(Q)$(MAKE) $(build)=libbpf
>   
>   $(OUTPUT)libbpf.so: $(BPF_IN)
> - $(QUIET_LINK)$(CC) --shared $^ -o $@
> + $(QUIET_LINK)$(CC) --shared -Wl,--version-script=$(VERSION_SCRIPT) \
> + $^ -o $@
>   
>   $(OUTPUT)libbpf.a: $(BPF_IN)
>   $(QUIET_LINK)$(RM) $@; $(AR) rcs $@ $^
> diff --git a/tools/lib/bpf/libbpf.map b/tools/lib/bpf/libbpf.map
> new file mode 100644
> index ..9fe416b68c7d
> --- /dev/null
> +++ b/tools/lib/bpf/libbpf.map
> @@ -0,0 +1,120 @@
> +LIBBPF_0.0.1 {
> + global:
> + bpf_btf_get_fd_by_id;

Do you think we could use this opportunities to
make naming more consistent? For example,
bpf_btf_get_fd_by_id => btf__get_fd_by_id?

> + bpf_create_map;
> + bpf_create_map_in_map;
> + bpf_create_map_in_map_node;
> + bpf_create_map_name;
> + bpf_create_map_node;
> + bpf_create_map_xattr;
> + bpf_load_btf;
> + bpf_load_program;
> + bpf_load_program_xattr;
> + bpf_map__btf_key_type_id;
> + bpf_map__btf_value_type_id;
> + bpf_map__def;
> + bpf_map_delete_elem; > +bpf_map__fd;
> + bpf_map_get_fd_by_id;
> + bpf_map_get_next_id;
> + bpf_map_get_next_key; > +   
> bpf_map__is_offload_neutral;
> + bpf_map_lookup_and_delete_elem;
> + bpf_map_lookup_elem;
> + bpf_map__name;
> + bpf_map__next;
> + bpf_map__pin;
> + bpf_map__prev;
> + bpf_map__priv;
> + bpf_map__reuse_fd;
> + bpf_map__set_ifindex;
> + bpf_map__set_priv;
> + bpf_map__unpin;
> + bpf_map_update_elem;
> + bpf_object__btf_fd;
> + bpf_object__close;
> + bpf_object__find_map_by_name;
> + bpf_object__find_map_by_offset;
> + bpf_object__find_program_by_title;
> + bpf_object__kversion;
> + bpf_object__load;
> + bpf_object__name;
> + bpf_object__next;
> + bpf_object__open;
> + bpf_object__open_buffer;
> + bpf_object__open_xattr;
> + bpf_object__pin;
> + bpf_object__pin_maps;
> + bpf_object__pin_programs;
> + bpf_object__priv;
> + bpf_object__set_priv;
> + bpf_object__unload;
> + bpf_object__unpin_maps;
> + bpf_object__unpin_programs;
> + bpf_obj_get;
> + bpf_obj_get_info_by_fd;
> + bpf_obj_pin;
> + bpf_perf_event_read_simple;
> + bpf_prog_attach;
> + bpf_prog_detach;
> + bpf_prog_detach2;
> + bpf_prog_get_fd_by_id;
> +  

[PATCH bpf-next] bpf: fix a libbpf loader issue

2018-11-21 Thread Yonghong Song
Commit 2993e0515bb4 ("tools/bpf: add support to read .BTF.ext sections")
added support to read .BTF.ext sections from an object file, create
and pass prog_btf_fd and func_info to the kernel.

The program btf_fd (prog->btf_fd) is initialized to be -1 to please
zclose so we do not need special handling dur prog close.
Passing -1 to the kernel, however, will cause loading error.
Passing btf_fd 0 to the kernel if prog->btf_fd is invalid
fixed the problem.

Fixes: 2993e0515bb4 ("tools/bpf: add support to read .BTF.ext sections")
Reported-by: Andrey Ignatov 
Reported-by: Emre Cantimur 
Tested-by: Andrey Ignatov 
Signed-off-by: Yonghong Song 
---
 tools/lib/bpf/libbpf.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c
index cb6565d79603..f022ac82e882 100644
--- a/tools/lib/bpf/libbpf.c
+++ b/tools/lib/bpf/libbpf.c
@@ -1387,7 +1387,7 @@ load_program(struct bpf_program *prog, struct bpf_insn 
*insns, int insns_cnt,
load_attr.license = license;
load_attr.kern_version = kern_version;
load_attr.prog_ifindex = prog->prog_ifindex;
-   load_attr.prog_btf_fd = prog->btf_fd;
+   load_attr.prog_btf_fd = prog->btf_fd >= 0 ? prog->btf_fd : 0;
load_attr.func_info = prog->func_info;
load_attr.func_info_rec_size = prog->func_info_rec_size;
load_attr.func_info_cnt = func_info_cnt;
-- 
2.17.1



[PATCH bpf-next v2] bpf: fix a compilation error when CONFIG_BPF_SYSCALL is not defined

2018-11-20 Thread Yonghong Song
Kernel test robot (l...@intel.com) reports a compilation error at
  https://www.spinics.net/lists/netdev/msg534913.html
introduced by commit 838e96904ff3 ("bpf: Introduce bpf_func_info").

If CONFIG_BPF is defined and CONFIG_BPF_SYSCALL is not defined,
the following error will appear:
  kernel/bpf/core.c:414: undefined reference to `btf_type_by_id'
  kernel/bpf/core.c:415: undefined reference to `btf_name_by_offset'

When CONFIG_BPF_SYSCALL is not defined,
let us define stub inline functions for btf_type_by_id()
and btf_name_by_offset() in include/linux/btf.h.
This way, the compilation failure can be avoided.

Fixes: 838e96904ff3 ("bpf: Introduce bpf_func_info")
Reported-by: kbuild test robot 
Cc: Martin KaFai Lau 
Signed-off-by: Yonghong Song 
---
 include/linux/btf.h | 14 ++
 1 file changed, 14 insertions(+)

Changelog:
  v1 -> v2:
. Two functions should be static inline functions
  if CONFIG_BPF_SYSCALL is not defined.

diff --git a/include/linux/btf.h b/include/linux/btf.h
index 7f2c0a4a45ea..8c2199b5d250 100644
--- a/include/linux/btf.h
+++ b/include/linux/btf.h
@@ -46,7 +46,21 @@ void btf_type_seq_show(const struct btf *btf, u32 type_id, 
void *obj,
   struct seq_file *m);
 int btf_get_fd_by_id(u32 id);
 u32 btf_id(const struct btf *btf);
+
+#ifdef CONFIG_BPF_SYSCALL
 const struct btf_type *btf_type_by_id(const struct btf *btf, u32 type_id);
 const char *btf_name_by_offset(const struct btf *btf, u32 offset);
+#else
+static inline const struct btf_type *btf_type_by_id(const struct btf *btf,
+   u32 type_id)
+{
+   return NULL;
+}
+static inline const char *btf_name_by_offset(const struct btf *btf,
+u32 offset)
+{
+   return NULL;
+}
+#endif
 
 #endif
-- 
2.17.1



[PATCH bpf-next] bpf: fix a compilation error when CONFIG_BPF_SYSCALL is not defined

2018-11-20 Thread Yonghong Song
Kernel test robot (l...@intel.com) reports a compilation error at
  https://www.spinics.net/lists/netdev/msg534913.html
introduced by commit 838e96904ff3 ("bpf: Introduce bpf_func_info").

If CONFIG_BPF is defined and CONFIG_BPF_SYSCALL is not defined,
the following error will appear:
  kernel/bpf/core.c:414: undefined reference to `btf_type_by_id'
  kernel/bpf/core.c:415: undefined reference to `btf_name_by_offset'

When CONFIG_BPF_SYSCALL is not defined,
let us define stub inline functions for btf_type_by_id()
and btf_name_by_offset() in include/linux/btf.h.
This way, the compilation failure can be avoided.

Fixes: 838e96904ff3 ("bpf: Introduce bpf_func_info")
Reported-by: kbuild test robot 
Cc: Martin KaFai Lau 
Signed-off-by: Yonghong Song 
---
 include/linux/btf.h | 12 
 1 file changed, 12 insertions(+)

diff --git a/include/linux/btf.h b/include/linux/btf.h
index 7f2c0a4a45ea..a5e893071861 100644
--- a/include/linux/btf.h
+++ b/include/linux/btf.h
@@ -46,7 +46,19 @@ void btf_type_seq_show(const struct btf *btf, u32 type_id, 
void *obj,
   struct seq_file *m);
 int btf_get_fd_by_id(u32 id);
 u32 btf_id(const struct btf *btf);
+
+#ifdef CONFIG_BPF_SYSCALL
 const struct btf_type *btf_type_by_id(const struct btf *btf, u32 type_id);
 const char *btf_name_by_offset(const struct btf *btf, u32 offset);
+#else
+const struct btf_type *btf_type_by_id(const struct btf *btf, u32 type_id)
+{
+   return NULL;
+}
+const char *btf_name_by_offset(const struct btf *btf, u32 offset)
+{
+   return NULL;
+}
+#endif
 
 #endif
-- 
2.17.1



Re: [PATCH bpf-next v2 02/13] bpf: btf: Add BTF_KIND_FUNC and BTF_KIND_FUNC_PROTO

2018-11-08 Thread Yonghong Song


On 11/8/18 2:56 PM, Edward Cree wrote:
> On 08/11/18 19:42, Alexei Starovoitov wrote:
>> same link let's continue at 1pm PST.
> So, one thing we didn't really get onto was maps, and you mentioned that it
>   wasn't really clear what I was proposing there.
> What I have in mind comes in two parts:
> 1) map type.  A new BTF_KIND_MAP with metadata 'key_type', 'value_type'
>   (both are type_ids referencing other BTF type records), describing the
>   type "map from key_type to value_type".
> 2) record in the 'instances' table.  This would have a name_off (the
>   name of the map), a type_id (pointing at a BTF_KIND_MAP in the 'types'
>   table), and potentially also some indication of what symbol (from
>   section 'maps') refers to this map.  This is pretty much the exact
>   same metadata that a function in the 'instances' table has, the only
>   differences being
>   (a) function's type_id points at a BTF_KIND_FUNC record
>   (b) function's symbol indication refers from .text section
>   (c) in future functions may be nested inside other functions, whereas
>   AIUI a map can't live inside a function.  (But a variable, which is
>   the other thing that would want to go in an 'instances' table, can.)
> So the 'instances' table record structure looks like
> 
> struct btf_instance {
>      __u32 type_id; /* Type of object declared.  An index into type section */
>      __u32 name_off; /* Name of object.  An offset into string section */
>      __u32 parent; /* Containing object if any (else 0).  An index into 
> instance section */
> };
> 
> and we extend the BTF header:
> 
> struct btf_header {
>      __u16   magic;
>      __u8    version;
>      __u8    flags;
>      __u32   hdr_len;
> 
>      /* All offsets are in bytes relative to the end of this header */
>      __u32   type_off;  /* offset of type section   */
>      __u32   type_len;  /* length of type section   */
>      __u32   str_off;   /* offset of string section */
>      __u32   str_len;   /* length of string section */
>      __u32   inst_off;  /* offset of instance section   */
>      __u32   inst_len;  /* length of instance section   */
> };
> 
> Then in the .BTF.ext section, we have both
> 
> struct bpf_func_info {
>      __u32 prog_symbol; /* Index of symbol giving address of subprog */
>      __u32 inst_id; /* Index into instance section */
> }
> 
> struct bpf_map_info {
> {
>      __u32 map_symbol; /* Index of symbol creating this map */
>      __u32 inst_id; /* Index into instance section */
> }
> 
> (either living in different subsections, or in a single table with
>   the addition of a kind field, or in a single table relying on the
>   ultimately referenced type to distinguish funcs from maps).
> 
> Note that the name (in btf_instance) of a map or function need not
>   match the name of the corresponding symbol; we use the .BTF.ext
>   section to tie together btf_instance IDs and symbol IDs.  Then in
>   the case of functions (subprogs), the prog_symbol can be looked
>   up in the ELF symbol table to find the address (== insn_offset)
>   of the subprog, as well as the section containing it (since that
>   might not be .text).  Similarly in the case of maps the BTF info
>   about the map is connected with the info in the maps section.
> 
> Now when the loader has munged this, what it passes to the kernel
>   might not have map_symbol, but instead map_fd.  Instead of
>   prog_symbol it will have whatever identifies the subprog in the
>   blob of stuff it feeds to the kernel (so probably insn_offset).
> 
> All this would of course require a bit more compiler support than
>   the current BPF_ANNOTATE_KV_PAIR, since that just causes the
>   existing BTF machinery to declare a specially constructed struct
>   type.  At the C level you could still have BPF_ANNOTATE_KV_PAIR
>   and the 'bpf_map_foo' name, but then the compiler would
>   recognise that and convert it into an instance record by looking
>   up the name 'foo' in its "maps" section.  That way the special
>   bpf_map_* handling (which ties map names to symbol names,

Compiler in general does not do transformation based on variable
or struct type names by default, so this probably should stay
in the loader.

>   also) would be entirely compiler-internal and not 'leak out' into
>   the definition of the format.  Frontends for other languages
>   which do possess a native map type (e.g. Python dict) might have
>   other ways of indicating the key/value type of a map at source
>   level (e.g. PEP 484) and could directly generate the appropriate
>   BTF_KIND_MAP and bpf_map_info records rather than (as they would
>   with the current design) having to encode the information as a
>   struct bpf_map_foo type-definition.

You mean a python application can generate bpf byte codes and
BTFs (include map types)? That will be different from the C/LLVM
use case. The python app. probably will be the loader as well.

One option is to pass BPF 

Re: [PATCH bpf-next v4 02/13] bpf: btf: Add BTF_KIND_FUNC

2018-11-08 Thread Yonghong Song


On 11/8/18 12:52 PM, Edward Cree wrote:
> On 08/11/18 20:36, Yonghong Song wrote:
>> This patch adds BTF_KIND_FUNC support to the type section.
>> BTF_KIND_FUNC is used to specify the signature of a
>> defined subprogram or the pointee of a function pointer.
>>
>> In BTF, the function type related data structures are
>>struct bpf_param {
>>  __u32 name_off; /* parameter name */
>>  __u32 type; /* parameter type */
>>};
>>struct bpf_type {
>>  __u32 name_off; /* function name */
>>  __u32 info; /* BTF_KIND_FUNC and num of parameters (#vlen) */
>>  __u32 type; /* return type */
>>}
>> The data layout of the function type:
>>struct bpf_type
>>#vlen number of bpf_param's
>>
>> For a defined subprogram with valid function body,
>>. function name and all parameter names except the vararg
>>  must be valid C identifier.
> Given that there's an intention to support other frontends besides
>   C, what's the reason for this restriction?

This (C) is the typical usage today. If later on other frontend
generates bpf programs with more relaxed symbol name requirement,
we can certainly relax the rule.

> 
>> For the pointee of a function pointer,
>>. function name and all parameter names will
>> have name_off = 0 to indicate a non-existing name.
> Why can't function pointer parameters have names?

Currently, both bcc and llvm does not retain function pointer
arguments in dwarf. For LLVM, the IR generation for function pointer
type discards the argument name. So I did the checking because
llvm does not generate it.

We can relax the restrictions later if the compiler starts
to keep argument names in the IR.

> E.g. imagine something like struct net_device_ops.  All those
>   function pointers have named parameters and that's relevant info
>   when debugging.
> 
> -Ed
> 


[PATCH bpf-next v4 12/13] tools/bpf: enhance test_btf file testing to test func info

2018-11-08 Thread Yonghong Song
Change the bpf programs test_btf_haskv.c and test_btf_nokv.c to
have two sections, and enhance test_btf.c test_file feature
to test btf func_info returned by the kernel.

Signed-off-by: Yonghong Song 
---
 tools/testing/selftests/bpf/test_btf.c   | 117 +--
 tools/testing/selftests/bpf/test_btf_haskv.c |  16 ++-
 tools/testing/selftests/bpf/test_btf_nokv.c  |  16 ++-
 3 files changed, 136 insertions(+), 13 deletions(-)

diff --git a/tools/testing/selftests/bpf/test_btf.c 
b/tools/testing/selftests/bpf/test_btf.c
index a5fcc30781d5..08a07358851b 100644
--- a/tools/testing/selftests/bpf/test_btf.c
+++ b/tools/testing/selftests/bpf/test_btf.c
@@ -2226,13 +2226,13 @@ static struct btf_file_test file_tests[] = {
 },
 };
 
-static int file_has_btf_elf(const char *fn)
+static int file_has_btf_elf(const char *fn, bool *has_btf_ext)
 {
Elf_Scn *scn = NULL;
GElf_Ehdr ehdr;
+   int ret = 0;
int elf_fd;
Elf *elf;
-   int ret;
 
if (CHECK(elf_version(EV_CURRENT) == EV_NONE,
  "elf_version(EV_CURRENT) == EV_NONE"))
@@ -2264,14 +2264,12 @@ static int file_has_btf_elf(const char *fn)
}
 
sh_name = elf_strptr(elf, ehdr.e_shstrndx, sh.sh_name);
-   if (!strcmp(sh_name, BTF_ELF_SEC)) {
+   if (!strcmp(sh_name, BTF_ELF_SEC))
ret = 1;
-   goto done;
-   }
+   if (!strcmp(sh_name, BTF_EXT_ELF_SEC))
+   *has_btf_ext = true;
}
 
-   ret = 0;
-
 done:
close(elf_fd);
elf_end(elf);
@@ -2281,15 +2279,24 @@ static int file_has_btf_elf(const char *fn)
 static int do_test_file(unsigned int test_num)
 {
const struct btf_file_test *test = _tests[test_num - 1];
+   const char *expected_fnames[] = {"_dummy_tracepoint",
+"test_long_fname_1",
+"test_long_fname_2"};
+   struct bpf_prog_info info = {};
struct bpf_object *obj = NULL;
+   struct bpf_func_info *finfo;
struct bpf_program *prog;
+   __u32 info_len, rec_size;
+   bool has_btf_ext = false;
+   struct btf *btf = NULL;
+   void *func_info = NULL;
struct bpf_map *map;
-   int err;
+   int i, err, prog_fd;
 
fprintf(stderr, "BTF libbpf test[%u] (%s): ", test_num,
test->file);
 
-   err = file_has_btf_elf(test->file);
+   err = file_has_btf_elf(test->file, _btf_ext);
if (err == -1)
return err;
 
@@ -2317,6 +2324,7 @@ static int do_test_file(unsigned int test_num)
err = bpf_object__load(obj);
if (CHECK(err < 0, "bpf_object__load: %d", err))
goto done;
+   prog_fd = bpf_program__fd(prog);
 
map = bpf_object__find_map_by_name(obj, "btf_map");
if (CHECK(!map, "btf_map not found")) {
@@ -2331,9 +2339,100 @@ static int do_test_file(unsigned int test_num)
  test->btf_kv_notfound))
goto done;
 
+   if (!jit_enabled || !has_btf_ext)
+   goto skip_jit;
+
+   /* get necessary program info */
+   info_len = sizeof(struct bpf_prog_info);
+   err = bpf_obj_get_info_by_fd(prog_fd, , _len);
+
+   if (CHECK(err == -1, "invalid get info (1st) errno:%d", errno)) {
+   fprintf(stderr, "%s\n", btf_log_buf);
+   err = -1;
+   goto done;
+   }
+   if (CHECK(info.func_info_cnt != 3,
+ "incorrect info.func_info_cnt (1st) %d",
+ info.func_info_cnt)) {
+   err = -1;
+   goto done;
+   }
+   rec_size = info.func_info_rec_size;
+   if (CHECK(rec_size < 4,
+ "incorrect info.func_info_rec_size (1st) %d\n", rec_size)) {
+   err = -1;
+   goto done;
+   }
+
+   func_info = malloc(info.func_info_cnt * rec_size);
+   if (CHECK(!func_info, "out of memeory")) {
+   err = -1;
+   goto done;
+   }
+
+   /* reset info to only retrieve func_info related data */
+   memset(, 0, sizeof(info));
+   info.func_info_cnt = 3;
+   info.func_info_rec_size = rec_size;
+   info.func_info = ptr_to_u64(func_info);
+
+   err = bpf_obj_get_info_by_fd(prog_fd, , _len);
+
+   if (CHECK(err == -1, "invalid get info (2nd) errno:%d", errno)) {
+   fprintf(stderr, "%s\n", btf_log_buf);
+   err = -1;
+   goto done;
+   }
+   if (CHECK(info.func_info_cnt != 3,
+ "incorrect info.func_info_cnt (2nd) %d",
+ info.func_info_cnt)) {
+   err = -1;
+   goto done;
+   }
+   if (CHECK(info.func_info_

[PATCH bpf-next v4 10/13] tools/bpf: do not use pahole if clang/llvm can generate BTF sections

2018-11-08 Thread Yonghong Song
Add additional checks in tools/testing/selftests/bpf and
samples/bpf such that if clang/llvm compiler can generate
BTF sections, do not use pahole.

Signed-off-by: Yonghong Song 
---
 samples/bpf/Makefile | 8 
 tools/testing/selftests/bpf/Makefile | 8 
 2 files changed, 16 insertions(+)

diff --git a/samples/bpf/Makefile b/samples/bpf/Makefile
index be0a961450bc..35444f4a846b 100644
--- a/samples/bpf/Makefile
+++ b/samples/bpf/Makefile
@@ -208,12 +208,20 @@ endif
 BTF_LLC_PROBE := $(shell $(LLC) -march=bpf -mattr=help 2>&1 | grep dwarfris)
 BTF_PAHOLE_PROBE := $(shell $(BTF_PAHOLE) --help 2>&1 | grep BTF)
 BTF_OBJCOPY_PROBE := $(shell $(LLVM_OBJCOPY) --help 2>&1 | grep -i 
'usage.*llvm')
+BTF_LLVM_PROBE := $(shell echo "int main() { return 0; }" | \
+ $(CLANG) -target bpf -O2 -g -c -x c - -o 
./llvm_btf_verify.o; \
+ readelf -S ./llvm_btf_verify.o | grep BTF; \
+ /bin/rm -f ./llvm_btf_verify.o)
 
+ifneq ($(BTF_LLVM_PROBE),)
+   EXTRA_CFLAGS += -g
+else
 ifneq ($(and $(BTF_LLC_PROBE),$(BTF_PAHOLE_PROBE),$(BTF_OBJCOPY_PROBE)),)
EXTRA_CFLAGS += -g
LLC_FLAGS += -mattr=dwarfris
DWARF2BTF = y
 endif
+endif
 
 # Trick to allow make to be run from this directory
 all:
diff --git a/tools/testing/selftests/bpf/Makefile 
b/tools/testing/selftests/bpf/Makefile
index e39dfb4e7970..63a321894419 100644
--- a/tools/testing/selftests/bpf/Makefile
+++ b/tools/testing/selftests/bpf/Makefile
@@ -124,7 +124,14 @@ $(OUTPUT)/test_stack_map.o: test_queue_stack_map.h
 BTF_LLC_PROBE := $(shell $(LLC) -march=bpf -mattr=help 2>&1 | grep dwarfris)
 BTF_PAHOLE_PROBE := $(shell $(BTF_PAHOLE) --help 2>&1 | grep BTF)
 BTF_OBJCOPY_PROBE := $(shell $(LLVM_OBJCOPY) --help 2>&1 | grep -i 
'usage.*llvm')
+BTF_LLVM_PROBE := $(shell echo "int main() { return 0; }" | \
+ $(CLANG) -target bpf -O2 -g -c -x c - -o 
./llvm_btf_verify.o; \
+ readelf -S ./llvm_btf_verify.o | grep BTF; \
+ /bin/rm -f ./llvm_btf_verify.o)
 
+ifneq ($(BTF_LLVM_PROBE),)
+   CLANG_FLAGS += -g
+else
 ifneq ($(BTF_LLC_PROBE),)
 ifneq ($(BTF_PAHOLE_PROBE),)
 ifneq ($(BTF_OBJCOPY_PROBE),)
@@ -134,6 +141,7 @@ ifneq ($(BTF_OBJCOPY_PROBE),)
 endif
 endif
 endif
+endif
 
 $(OUTPUT)/%.o: %.c
$(CLANG) $(CLANG_FLAGS) \
-- 
2.17.1



[PATCH bpf-next v4 13/13] tools/bpf: bpftool: add support for func types

2018-11-08 Thread Yonghong Song
This patch added support to print function signature
if btf func_info is available. Note that ksym
now uses function name instead of prog_name as
prog_name has a limit of 16 bytes including
ending '\0'.

The following is a sample output for selftests
test_btf with file test_btf_haskv.o for translated insns
and jited insns respectively.

  $ bpftool prog dump xlated id 1
  int _dummy_tracepoint(struct dummy_tracepoint_args * arg):
 0: (85) call pc+2#bpf_prog_2dcecc18072623fc_test_long_fname_1
 1: (b7) r0 = 0
 2: (95) exit
  int test_long_fname_1(struct dummy_tracepoint_args * arg):
 3: (85) call pc+1#bpf_prog_89d64e4abf0f0126_test_long_fname_2
 4: (95) exit
  int test_long_fname_2(struct dummy_tracepoint_args * arg):
 5: (b7) r2 = 0
 6: (63) *(u32 *)(r10 -4) = r2
 7: (79) r1 = *(u64 *)(r1 +8)
 ...
 22: (07) r1 += 1
 23: (63) *(u32 *)(r0 +4) = r1
 24: (95) exit

  $ bpftool prog dump jited id 1
  int _dummy_tracepoint(struct dummy_tracepoint_args * arg):
  bpf_prog_b07ccb89267cf242__dummy_tracepoint:
 0:   push   %rbp
 1:   mov%rsp,%rbp
..
3c:   add$0x28,%rbp
40:   leaveq
41:   retq

  int test_long_fname_1(struct dummy_tracepoint_args * arg):
  bpf_prog_2dcecc18072623fc_test_long_fname_1:
 0:   push   %rbp
 1:   mov%rsp,%rbp
..
3a:   add$0x28,%rbp
3e:   leaveq
3f:   retq

  int test_long_fname_2(struct dummy_tracepoint_args * arg):
  bpf_prog_89d64e4abf0f0126_test_long_fname_2:
 0:   push   %rbp
 1:   mov%rsp,%rbp
..
80:   add$0x28,%rbp
84:   leaveq
85:   retq

Signed-off-by: Yonghong Song 
---
 tools/bpf/bpftool/btf_dumper.c| 98 +++
 tools/bpf/bpftool/main.h  |  2 +
 tools/bpf/bpftool/prog.c  | 56 ++
 tools/bpf/bpftool/xlated_dumper.c | 33 +++
 tools/bpf/bpftool/xlated_dumper.h |  3 +
 5 files changed, 192 insertions(+)

diff --git a/tools/bpf/bpftool/btf_dumper.c b/tools/bpf/bpftool/btf_dumper.c
index 55bc512a1831..64b63d53a143 100644
--- a/tools/bpf/bpftool/btf_dumper.c
+++ b/tools/bpf/bpftool/btf_dumper.c
@@ -249,3 +249,101 @@ int btf_dumper_type(const struct btf_dumper *d, __u32 
type_id,
 {
return btf_dumper_do_type(d, type_id, 0, data);
 }
+
+#define BTF_PRINT_ARG(...) \
+   do {\
+   pos += snprintf(func_sig + pos, size - pos, \
+   __VA_ARGS__);   \
+   if (pos >= size)\
+   return -1;  \
+   } while (0)
+#define BTF_PRINT_TYPE(type)   \
+   do {\
+   pos = __btf_dumper_type_only(btf, type, func_sig,   \
+pos, size);\
+   if (pos == -1)  \
+   return -1;  \
+   } while (0)
+
+static int __btf_dumper_type_only(struct btf *btf, __u32 type_id,
+ char *func_sig, int pos, int size)
+{
+   const struct btf_type *t = btf__type_by_id(btf, type_id);
+   const struct btf_array *array;
+   int i, vlen;
+
+   switch (BTF_INFO_KIND(t->info)) {
+   case BTF_KIND_INT:
+   BTF_PRINT_ARG("%s ", btf__name_by_offset(btf, t->name_off));
+   break;
+   case BTF_KIND_STRUCT:
+   BTF_PRINT_ARG("struct %s ",
+ btf__name_by_offset(btf, t->name_off));
+   break;
+   case BTF_KIND_UNION:
+   BTF_PRINT_ARG("union %s ",
+ btf__name_by_offset(btf, t->name_off));
+   break;
+   case BTF_KIND_ENUM:
+   BTF_PRINT_ARG("enum %s ",
+ btf__name_by_offset(btf, t->name_off));
+   break;
+   case BTF_KIND_ARRAY:
+   array = (struct btf_array *)(t + 1);
+   BTF_PRINT_TYPE(array->type);
+   BTF_PRINT_ARG("[%d]", array->nelems);
+   break;
+   case BTF_KIND_PTR:
+   BTF_PRINT_TYPE(t->type);
+   BTF_PRINT_ARG("* ");
+   break;
+   case BTF_KIND_UNKN:
+   case BTF_KIND_FWD:
+   case BTF_KIND_TYPEDEF:
+   return -1;
+   case BTF_KIND_VOLATILE:
+   BTF_PRINT_ARG("volatile ");
+   BTF_PRINT_TYPE(t->type);
+   break;
+   case BTF_KIND_CONST:
+   BTF_PRINT_ARG("const ");
+   BTF_PRINT_TYPE(t->type);
+   

[PATCH bpf-next v4 04/13] tools/bpf: add btf func unit tests in selftest test_btf

2018-11-08 Thread Yonghong Song
Add several BTF_KIND_FUNC unit tests in bpf selftest test_btf.

Signed-off-by: Martin KaFai Lau 
Signed-off-by: Yonghong Song 
---
 tools/lib/bpf/btf.c|   3 +
 tools/testing/selftests/bpf/test_btf.c | 262 +
 2 files changed, 265 insertions(+)

diff --git a/tools/lib/bpf/btf.c b/tools/lib/bpf/btf.c
index 449591aa9900..6da816d64ca1 100644
--- a/tools/lib/bpf/btf.c
+++ b/tools/lib/bpf/btf.c
@@ -165,6 +165,9 @@ static int btf_parse_type_sec(struct btf *btf, 
btf_print_fn_t err_log)
case BTF_KIND_ENUM:
next_type += vlen * sizeof(struct btf_enum);
break;
+   case BTF_KIND_FUNC:
+   next_type += vlen * sizeof(struct btf_param);
+   break;
case BTF_KIND_TYPEDEF:
case BTF_KIND_PTR:
case BTF_KIND_FWD:
diff --git a/tools/testing/selftests/bpf/test_btf.c 
b/tools/testing/selftests/bpf/test_btf.c
index f42b3396d622..0e63c99c44b1 100644
--- a/tools/testing/selftests/bpf/test_btf.c
+++ b/tools/testing/selftests/bpf/test_btf.c
@@ -1374,6 +1374,268 @@ static struct btf_raw_test raw_tests[] = {
.map_create_err = true,
 },
 
+{
+   .descr = "func pointer #1",
+   .raw_types = {
+   BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4),  /* [1] */
+   BTF_TYPE_INT_ENC(0, 0, 0, 32, 4),   /* [2] */
+   /* int (*func)(int, unsigned int) */
+   BTF_TYPE_ENC(0, BTF_INFO_ENC(BTF_KIND_FUNC, 0, 2), 1),  /* [3] 
*/
+   0, 1, 0, 2,
+   BTF_TYPE_ENC(0, BTF_INFO_ENC(BTF_KIND_PTR, 0, 0), 3),   /* [4] 
*/
+   BTF_END_RAW,
+   },
+   .str_sec = "",
+   .str_sec_size = sizeof(""),
+   .map_type = BPF_MAP_TYPE_ARRAY,
+   .map_name = "func_type_check_btf",
+   .key_size = sizeof(int),
+   .value_size = sizeof(int),
+   .key_type_id = 1,
+   .value_type_id = 1,
+   .max_entries = 4,
+},
+
+{
+   .descr = "func pointer #2",
+   .raw_types = {
+   BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4),  /* [1] */
+   BTF_TYPE_INT_ENC(0, 0, 0, 32, 4),   /* [2] */
+   /* void (*func)(int, unsigned int, ) */
+   BTF_TYPE_ENC(0, BTF_INFO_ENC(BTF_KIND_FUNC, 0, 3), 0),  /* [3] 
*/
+   0, 1, 0, 2, 0, 0,
+   BTF_TYPE_ENC(0, BTF_INFO_ENC(BTF_KIND_PTR, 0, 0), 3),   /* [4] 
*/
+   BTF_END_RAW,
+   },
+   .str_sec = "",
+   .str_sec_size = sizeof(""),
+   .map_type = BPF_MAP_TYPE_ARRAY,
+   .map_name = "func_type_check_btf",
+   .key_size = sizeof(int),
+   .value_size = sizeof(int),
+   .key_type_id = 1,
+   .value_type_id = 1,
+   .max_entries = 4,
+},
+
+{
+   .descr = "func pointer #3",
+   .raw_types = {
+   BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4),  /* [1] */
+   BTF_TYPE_INT_ENC(0, 0, 0, 32, 4),   /* [2] */
+   /* void (*func)(void, int, unsigned int) */
+   BTF_TYPE_ENC(0, BTF_INFO_ENC(BTF_KIND_FUNC, 0, 3), 0),  /* [3] 
*/
+   0, 1, 0, 0, 0, 2,
+   BTF_TYPE_ENC(0, BTF_INFO_ENC(BTF_KIND_PTR, 0, 0), 3),   /* [4] 
*/
+   BTF_END_RAW,
+   },
+   .str_sec = "",
+   .str_sec_size = sizeof(""),
+   .map_type = BPF_MAP_TYPE_ARRAY,
+   .map_name = "func_type_check_btf",
+   .key_size = sizeof(int),
+   .value_size = sizeof(int),
+   .key_type_id = 1,
+   .value_type_id = 1,
+   .max_entries = 4,
+   .btf_load_err = true,
+   .err_str = "Invalid arg#2",
+},
+
+{
+   .descr = "func pointer #4",
+   .raw_types = {
+   BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4),  /* [1] */
+   BTF_TYPE_INT_ENC(0, 0, 0, 32, 4),   /* [2] */
+   /*
+* Testing:
+* BTF_KIND_CONST => BTF_KIND_TYPEDEF => BTF_KIND_PTR =>
+* BTF_KIND_FUNC
+*/
+   /* typedef void (*func_ptr)(int, unsigned int) */
+   BTF_TYPE_ENC(0, BTF_INFO_ENC(BTF_KIND_TYPEDEF, 0, 0), 5),/* [3] 
*/
+   /* const func_ptr */
+   BTF_TYPE_ENC(0, BTF_INFO_ENC(BTF_KIND_CONST, 0, 0), 3), /* [4] 
*/
+   BTF_TYPE_ENC(0, BTF_INFO_ENC(BTF_KIND_PTR, 0, 0), 6),   /* [5] 
*/
+   BTF_TYPE_ENC(0, BTF_INFO_ENC(BTF_KIND_FUNC, 0, 2), 0),  /* [6] 
*/
+   0, 1, 0, 2,
+   BTF_END_RAW,
+   },
+   .str_sec = "",
+   .str_sec_size = sizeof(""),
+   .map_type = BPF_MAP_TYPE_ARRAY,
+   .map_name = "func_type_check_btf",
+   .key_size = sizeof(int),
+   .value_size = sizeof(int),
+  

[PATCH bpf-next v4 11/13] tools/bpf: refactor to implement btf_get_from_id() in lib/bpf

2018-11-08 Thread Yonghong Song
The function get_btf() is implemented in tools/bpf/bpftool/map.c
to get a btf structure given a map_info. This patch
refactored this function to be function btf_get_from_id()
in tools/lib/bpf so that it can be used later.

Signed-off-by: Yonghong Song 
---
 tools/bpf/bpftool/map.c | 68 ++--
 tools/lib/bpf/btf.c | 69 +
 tools/lib/bpf/btf.h |  1 +
 3 files changed, 72 insertions(+), 66 deletions(-)

diff --git a/tools/bpf/bpftool/map.c b/tools/bpf/bpftool/map.c
index 7bf38f0e152e..1b8a75fa0471 100644
--- a/tools/bpf/bpftool/map.c
+++ b/tools/bpf/bpftool/map.c
@@ -215,70 +215,6 @@ static int do_dump_btf(const struct btf_dumper *d,
return ret;
 }
 
-static int get_btf(struct bpf_map_info *map_info, struct btf **btf)
-{
-   struct bpf_btf_info btf_info = { 0 };
-   __u32 len = sizeof(btf_info);
-   __u32 last_size;
-   int btf_fd;
-   void *ptr;
-   int err;
-
-   err = 0;
-   *btf = NULL;
-   btf_fd = bpf_btf_get_fd_by_id(map_info->btf_id);
-   if (btf_fd < 0)
-   return 0;
-
-   /* we won't know btf_size until we call bpf_obj_get_info_by_fd(). so
-* let's start with a sane default - 4KiB here - and resize it only if
-* bpf_obj_get_info_by_fd() needs a bigger buffer.
-*/
-   btf_info.btf_size = 4096;
-   last_size = btf_info.btf_size;
-   ptr = malloc(last_size);
-   if (!ptr) {
-   err = -ENOMEM;
-   goto exit_free;
-   }
-
-   bzero(ptr, last_size);
-   btf_info.btf = ptr_to_u64(ptr);
-   err = bpf_obj_get_info_by_fd(btf_fd, _info, );
-
-   if (!err && btf_info.btf_size > last_size) {
-   void *temp_ptr;
-
-   last_size = btf_info.btf_size;
-   temp_ptr = realloc(ptr, last_size);
-   if (!temp_ptr) {
-   err = -ENOMEM;
-   goto exit_free;
-   }
-   ptr = temp_ptr;
-   bzero(ptr, last_size);
-   btf_info.btf = ptr_to_u64(ptr);
-   err = bpf_obj_get_info_by_fd(btf_fd, _info, );
-   }
-
-   if (err || btf_info.btf_size > last_size) {
-   err = errno;
-   goto exit_free;
-   }
-
-   *btf = btf__new((__u8 *)btf_info.btf, btf_info.btf_size, NULL);
-   if (IS_ERR(*btf)) {
-   err = PTR_ERR(*btf);
-   *btf = NULL;
-   }
-
-exit_free:
-   close(btf_fd);
-   free(ptr);
-
-   return err;
-}
-
 static json_writer_t *get_btf_writer(void)
 {
json_writer_t *jw = jsonw_new(stdout);
@@ -765,7 +701,7 @@ static int do_dump(int argc, char **argv)
 
prev_key = NULL;
 
-   err = get_btf(, );
+   err = btf_get_from_id(info.btf_id, );
if (err) {
p_err("failed to get btf");
goto exit_free;
@@ -909,7 +845,7 @@ static int do_lookup(int argc, char **argv)
}
 
/* here means bpf_map_lookup_elem() succeeded */
-   err = get_btf(, );
+   err = btf_get_from_id(info.btf_id, );
if (err) {
p_err("failed to get btf");
goto exit_free;
diff --git a/tools/lib/bpf/btf.c b/tools/lib/bpf/btf.c
index 11579ed4ef6c..2a914ab65cbc 100644
--- a/tools/lib/bpf/btf.c
+++ b/tools/lib/bpf/btf.c
@@ -49,6 +49,11 @@ struct bpf_func_info_min {
__u32   type_id;
 };
 
+static inline __u64 ptr_to_u64(const void *ptr)
+{
+   return (__u64) (unsigned long) ptr;
+}
+
 static int btf_add_type(struct btf *btf, struct btf_type *t)
 {
if (btf->types_size - btf->nr_types < 2) {
@@ -409,6 +414,70 @@ const char *btf__name_by_offset(const struct btf *btf, 
__u32 offset)
return NULL;
 }
 
+int btf_get_from_id(__u32 id, struct btf **btf)
+{
+   struct bpf_btf_info btf_info = { 0 };
+   __u32 len = sizeof(btf_info);
+   __u32 last_size;
+   int btf_fd;
+   void *ptr;
+   int err;
+
+   err = 0;
+   *btf = NULL;
+   btf_fd = bpf_btf_get_fd_by_id(id);
+   if (btf_fd < 0)
+   return 0;
+
+   /* we won't know btf_size until we call bpf_obj_get_info_by_fd(). so
+* let's start with a sane default - 4KiB here - and resize it only if
+* bpf_obj_get_info_by_fd() needs a bigger buffer.
+*/
+   btf_info.btf_size = 4096;
+   last_size = btf_info.btf_size;
+   ptr = malloc(last_size);
+   if (!ptr) {
+   err = -ENOMEM;
+   goto exit_free;
+   }
+
+   bzero(ptr, last_size);
+   btf_info.btf = ptr_to_u64(ptr);
+   err = bpf_obj_get_info_by_fd(btf_fd, _info, );
+
+   if (!err && btf_info.btf_size > last_size) {
+   void *temp_ptr;
+
+   last_size = btf_info.btf_size;
+   temp_ptr = realloc(ptr, last_size);
+   if (!temp_ptr) {
+   

[PATCH bpf-next v4 09/13] tools/bpf: add support to read .BTF.ext sections

2018-11-08 Thread Yonghong Song
The .BTF section is already available to encode types.
These types can be used for map
pretty print. The whole .BTF will be passed to the
kernel as well for which kernel can verify and return
to the user space for pretty print etc.

The llvm patch at https://reviews.llvm.org/D53736
will generate .BTF section and one more section .BTF.ext.
The .BTF.ext section encodes function type
information and line information. Note that
this patch set only supports function type info.
The functionality is implemented in libbpf.

The .BTF section can be directly loaded into the
kernel, and the .BTF.ext section cannot. The loader
may need to do some relocation and merging,
similar to merging multiple code sections, before
loading into the kernel.

Acked-by: Martin KaFai Lau 
Signed-off-by: Yonghong Song 
---
 tools/lib/bpf/bpf.c|  46 ++-
 tools/lib/bpf/btf.c| 274 +
 tools/lib/bpf/btf.h|  50 
 tools/lib/bpf/libbpf.c |  87 ++---
 4 files changed, 442 insertions(+), 15 deletions(-)

diff --git a/tools/lib/bpf/bpf.c b/tools/lib/bpf/bpf.c
index 06fc5e91ac51..ce1822194590 100644
--- a/tools/lib/bpf/bpf.c
+++ b/tools/lib/bpf/bpf.c
@@ -177,6 +177,7 @@ int bpf_load_program_xattr(const struct 
bpf_load_program_attr *load_attr,
   char *log_buf, size_t log_buf_sz)
 {
union bpf_attr attr;
+   void *finfo = NULL;
__u32 name_len;
int fd;
 
@@ -207,12 +208,55 @@ int bpf_load_program_xattr(const struct 
bpf_load_program_attr *load_attr,
if (fd >= 0 || !log_buf || !log_buf_sz)
return fd;
 
+   /* After bpf_prog_load, the kernel may modify certain attributes
+* to give user space a hint how to deal with loading failure.
+* Check to see whether we can make some changes and load again.
+*/
+   if (errno == E2BIG && attr.func_info_cnt &&
+   attr.func_info_rec_size < load_attr->func_info_rec_size) {
+   __u32 actual_rec_size = load_attr->func_info_rec_size;
+   __u32 expected_rec_size = attr.func_info_rec_size;
+   __u32 finfo_cnt = load_attr->func_info_cnt;
+   __u64 finfo_len = actual_rec_size * finfo_cnt;
+   const void *orecord;
+   void *nrecord;
+   int i;
+
+   finfo = malloc(finfo_len);
+   if (!finfo)
+   /* further try with log buffer won't help */
+   return fd;
+
+   /* zero out bytes kernel does not understand */
+   orecord = load_attr->func_info;
+   nrecord = finfo;
+   for (i = 0; i < load_attr->func_info_cnt; i++) {
+   memcpy(nrecord, orecord, expected_rec_size);
+   memset(nrecord + expected_rec_size, 0,
+  actual_rec_size - expected_rec_size);
+   orecord += actual_rec_size;
+   nrecord += actual_rec_size;
+   }
+
+   /* try with corrected func info records */
+   attr.func_info = ptr_to_u64(finfo);
+   attr.func_info_rec_size = load_attr->func_info_rec_size;
+
+   fd = sys_bpf(BPF_PROG_LOAD, , sizeof(attr));
+
+   if (fd >= 0 || !log_buf || !log_buf_sz)
+   goto done;
+   }
+
/* Try again with log */
attr.log_buf = ptr_to_u64(log_buf);
attr.log_size = log_buf_sz;
attr.log_level = 1;
log_buf[0] = 0;
-   return sys_bpf(BPF_PROG_LOAD, , sizeof(attr));
+   fd = sys_bpf(BPF_PROG_LOAD, , sizeof(attr));
+done:
+   free(finfo);
+   return fd;
 }
 
 int bpf_load_program(enum bpf_prog_type type, const struct bpf_insn *insns,
diff --git a/tools/lib/bpf/btf.c b/tools/lib/bpf/btf.c
index 6da816d64ca1..11579ed4ef6c 100644
--- a/tools/lib/bpf/btf.c
+++ b/tools/lib/bpf/btf.c
@@ -37,6 +37,18 @@ struct btf {
int fd;
 };
 
+struct btf_ext {
+   void *func_info;
+   __u32 func_info_rec_size;
+   __u32 func_info_len;
+};
+
+/* The minimum bpf_func_info checked by the loader */
+struct bpf_func_info_min {
+   __u32   insn_offset;
+   __u32   type_id;
+};
+
 static int btf_add_type(struct btf *btf, struct btf_type *t)
 {
if (btf->types_size - btf->nr_types < 2) {
@@ -396,3 +408,265 @@ const char *btf__name_by_offset(const struct btf *btf, 
__u32 offset)
else
return NULL;
 }
+
+static int btf_ext_validate_func_info(const void *finfo, __u32 size,
+ btf_print_fn_t err_log)
+{
+   int sec_hdrlen = sizeof(struct btf_sec_func_info);
+   __u32 size_left, num_records, record_size;
+   const struct btf_sec_func_info *sinfo;
+   __u64 total_record_size;
+
+   /* At least a func_info record size */
+   if (size < sizeof(__u32)) {
+  

[PATCH bpf-next v4 08/13] tools/bpf: extends test_btf to test load/retrieve func_type info

2018-11-08 Thread Yonghong Song
A two function bpf program is loaded with btf and func_info.
After successful prog load, the bpf_get_info syscall is called
to retrieve prog info to ensure the types returned from the
kernel matches the types passed to the kernel from the
user space.

Several negative tests are also added to test loading/retriving
of func_type info.

Acked-by: Martin KaFai Lau 
Signed-off-by: Yonghong Song 
---
 tools/testing/selftests/bpf/test_btf.c | 315 -
 1 file changed, 312 insertions(+), 3 deletions(-)

diff --git a/tools/testing/selftests/bpf/test_btf.c 
b/tools/testing/selftests/bpf/test_btf.c
index 0e63c99c44b1..a5fcc30781d5 100644
--- a/tools/testing/selftests/bpf/test_btf.c
+++ b/tools/testing/selftests/bpf/test_btf.c
@@ -5,6 +5,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -22,9 +23,13 @@
 #include "bpf_rlimit.h"
 #include "bpf_util.h"
 
+#define MAX_INSNS  512
+#define MAX_SUBPROGS   16
+
 static uint32_t pass_cnt;
 static uint32_t error_cnt;
 static uint32_t skip_cnt;
+static bool jit_enabled;
 
 #define CHECK(condition, format...) ({ \
int __ret = !!(condition);  \
@@ -60,6 +65,24 @@ static int __base_pr(const char *format, ...)
return err;
 }
 
+static bool is_jit_enabled(void)
+{
+   const char *jit_sysctl = "/proc/sys/net/core/bpf_jit_enable";
+   bool enabled = false;
+   int sysctl_fd;
+
+   sysctl_fd = open(jit_sysctl, 0, O_RDONLY);
+   if (sysctl_fd != -1) {
+   char tmpc;
+
+   if (read(sysctl_fd, , sizeof(tmpc)) == 1)
+   enabled = (tmpc != '0');
+   close(sysctl_fd);
+   }
+
+   return enabled;
+}
+
 #define BTF_INFO_ENC(kind, root, vlen) \
((!!(root) << 31) | ((kind) << 24) | ((vlen) & BTF_MAX_VLEN))
 
@@ -103,6 +126,7 @@ static struct args {
bool get_info_test;
bool pprint_test;
bool always_log;
+   bool func_type_test;
 } args;
 
 static char btf_log_buf[BTF_LOG_BUF_SIZE];
@@ -2739,16 +2763,293 @@ static int test_pprint(void)
return err;
 }
 
+static struct btf_func_type_test {
+   const char *descr;
+   const char *str_sec;
+   __u32 raw_types[MAX_NR_RAW_TYPES];
+   __u32 str_sec_size;
+   struct bpf_insn insns[MAX_INSNS];
+   __u32 prog_type;
+   __u32 func_info[MAX_SUBPROGS][2];
+   __u32 func_info_rec_size;
+   __u32 func_info_cnt;
+   bool expected_prog_load_failure;
+} func_type_test[] = {
+
+{
+   .descr = "func_type test #1",
+   .str_sec = "\0int\0unsigned int\0funcA\0a\0b\0funcB\0a\0b",
+   .raw_types = {
+   BTF_TYPE_INT_ENC(NAME_TBD, BTF_INT_SIGNED, 0, 32, 4),  /* [1] */
+   BTF_TYPE_INT_ENC(NAME_TBD, 0, 0, 32, 4),   /* [2] */
+   BTF_TYPE_ENC(NAME_TBD, BTF_INFO_ENC(BTF_KIND_FUNC, 0, 2), 1),  
/* [3] */
+   NAME_TBD, 1, NAME_TBD, 2,
+   BTF_TYPE_ENC(NAME_TBD, BTF_INFO_ENC(BTF_KIND_FUNC, 0, 2), 1),  
/* [4] */
+   NAME_TBD, 2, NAME_TBD, 1,
+   BTF_END_RAW,
+   },
+   .str_sec_size = sizeof("\0int\0unsigned int\0funcA\0a\0b\0funcB\0a\0b"),
+   .insns = {
+   BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 1, 0, 2),
+   BPF_MOV64_IMM(BPF_REG_0, 1),
+   BPF_EXIT_INSN(),
+   BPF_MOV64_IMM(BPF_REG_0, 2),
+   BPF_EXIT_INSN(),
+   },
+   .prog_type = BPF_PROG_TYPE_TRACEPOINT,
+   .func_info = { {0, 3}, {3, 4} },
+   .func_info_rec_size = 8,
+   .func_info_cnt = 2,
+},
+
+{
+   .descr = "func_type test #2",
+   .str_sec = "\0int\0unsigned int\0funcA\0a\0b\0funcB\0a\0b",
+   .raw_types = {
+   BTF_TYPE_INT_ENC(NAME_TBD, BTF_INT_SIGNED, 0, 32, 4),  /* [1] */
+   BTF_TYPE_INT_ENC(NAME_TBD, 0, 0, 32, 4),   /* [2] */
+   BTF_TYPE_ENC(NAME_TBD, BTF_INFO_ENC(BTF_KIND_FUNC, 0, 2), 1),  
/* [3] */
+   NAME_TBD, 1, NAME_TBD, 2,
+   BTF_TYPE_ENC(NAME_TBD, BTF_INFO_ENC(BTF_KIND_FUNC, 0, 2), 1),  
/* [4] */
+   NAME_TBD, 2, NAME_TBD, 1,
+   BTF_END_RAW,
+   },
+   .str_sec_size = sizeof("\0int\0unsigned int\0funcA\0a\0b\0funcB\0a\0b"),
+   .insns = {
+   BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 1, 0, 2),
+   BPF_MOV64_IMM(BPF_REG_0, 1),
+   BPF_EXIT_INSN(),
+   BPF_MOV64_IMM(BPF_REG_0, 2),
+   BPF_EXIT_INSN(),
+   },
+   .prog_type = BPF_PROG_TYPE_TRACEPOINT,
+   .func_info = { {0, 3}, {3, 4} },
+   /* incorrect func_info_rec_size */
+   .func_info_rec_size = 4,
+   .func_info_cnt = 2,
+   .expected_prog_load_failure = true,
+},
+
+{
+   .descr = "func_type test #3",
+  

[PATCH bpf-next v4 06/13] tools/bpf: sync kernel uapi bpf.h header to tools directory

2018-11-08 Thread Yonghong Song
The kernel uapi bpf.h is synced to tools directory.

Acked-by: Martin KaFai Lau 
Signed-off-by: Yonghong Song 
---
 tools/include/uapi/linux/bpf.h | 13 +
 1 file changed, 13 insertions(+)

diff --git a/tools/include/uapi/linux/bpf.h b/tools/include/uapi/linux/bpf.h
index 852dc17ab47a..28db552a1eed 100644
--- a/tools/include/uapi/linux/bpf.h
+++ b/tools/include/uapi/linux/bpf.h
@@ -335,6 +335,10 @@ union bpf_attr {
 * (context accesses, allowed helpers, etc).
 */
__u32   expected_attach_type;
+   __u32   prog_btf_fd;/* fd pointing to BTF type data 
*/
+   __u32   func_info_rec_size; /* userspace 
bpf_func_info size */
+   __aligned_u64   func_info;  /* func info */
+   __u32   func_info_cnt;  /* number of bpf_func_info 
records */
};
 
struct { /* anonymous struct used by BPF_OBJ_* commands */
@@ -2631,6 +2635,10 @@ struct bpf_prog_info {
__u32 nr_jited_func_lens;
__aligned_u64 jited_ksyms;
__aligned_u64 jited_func_lens;
+   __u32 btf_id;
+   __u32 func_info_rec_size;
+   __aligned_u64 func_info;
+   __u32 func_info_cnt;
 } __attribute__((aligned(8)));
 
 struct bpf_map_info {
@@ -2942,4 +2950,9 @@ struct bpf_flow_keys {
};
 };
 
+struct bpf_func_info {
+   __u32   insn_offset;
+   __u32   type_id;
+};
+
 #endif /* _UAPI__LINUX_BPF_H__ */
-- 
2.17.1



[PATCH bpf-next v4 01/13] bpf: btf: Break up btf_type_is_void()

2018-11-08 Thread Yonghong Song
This patch breaks up btf_type_is_void() into
btf_type_is_void() and btf_type_is_fwd().

It also adds btf_type_nosize() to better describe it is
testing a type has nosize info.

Signed-off-by: Martin KaFai Lau 
---
 kernel/bpf/btf.c | 37 ++---
 1 file changed, 22 insertions(+), 15 deletions(-)

diff --git a/kernel/bpf/btf.c b/kernel/bpf/btf.c
index ee4c82667d65..2a50d87de485 100644
--- a/kernel/bpf/btf.c
+++ b/kernel/bpf/btf.c
@@ -306,15 +306,22 @@ static bool btf_type_is_modifier(const struct btf_type *t)
 
 static bool btf_type_is_void(const struct btf_type *t)
 {
-   /* void => no type and size info.
-* Hence, FWD is also treated as void.
-*/
-   return t == _void || BTF_INFO_KIND(t->info) == BTF_KIND_FWD;
+   return t == _void;
+}
+
+static bool btf_type_is_fwd(const struct btf_type *t)
+{
+   return BTF_INFO_KIND(t->info) == BTF_KIND_FWD;
+}
+
+static bool btf_type_nosize(const struct btf_type *t)
+{
+   return btf_type_is_void(t) || btf_type_is_fwd(t);
 }
 
-static bool btf_type_is_void_or_null(const struct btf_type *t)
+static bool btf_type_nosize_or_null(const struct btf_type *t)
 {
-   return !t || btf_type_is_void(t);
+   return !t || btf_type_nosize(t);
 }
 
 /* union is only a special case of struct:
@@ -826,7 +833,7 @@ const struct btf_type *btf_type_id_size(const struct btf 
*btf,
u32 size = 0;
 
size_type = btf_type_by_id(btf, size_type_id);
-   if (btf_type_is_void_or_null(size_type))
+   if (btf_type_nosize_or_null(size_type))
return NULL;
 
if (btf_type_has_size(size_type)) {
@@ -842,7 +849,7 @@ const struct btf_type *btf_type_id_size(const struct btf 
*btf,
size = btf->resolved_sizes[size_type_id];
size_type_id = btf->resolved_ids[size_type_id];
size_type = btf_type_by_id(btf, size_type_id);
-   if (btf_type_is_void(size_type))
+   if (btf_type_nosize_or_null(size_type))
return NULL;
}
 
@@ -1164,7 +1171,7 @@ static int btf_modifier_resolve(struct btf_verifier_env 
*env,
}
 
/* "typedef void new_void", "const void"...etc */
-   if (btf_type_is_void(next_type))
+   if (btf_type_is_void(next_type) || btf_type_is_fwd(next_type))
goto resolved;
 
if (!env_type_is_resolve_sink(env, next_type) &&
@@ -1178,7 +1185,7 @@ static int btf_modifier_resolve(struct btf_verifier_env 
*env,
 * pretty print).
 */
if (!btf_type_id_size(btf, _type_id, _type_size) &&
-   !btf_type_is_void(btf_type_id_resolve(btf, _type_id))) {
+   !btf_type_nosize(btf_type_id_resolve(btf, _type_id))) {
btf_verifier_log_type(env, v->t, "Invalid type_id");
return -EINVAL;
}
@@ -1205,7 +1212,7 @@ static int btf_ptr_resolve(struct btf_verifier_env *env,
}
 
/* "void *" */
-   if (btf_type_is_void(next_type))
+   if (btf_type_is_void(next_type) || btf_type_is_fwd(next_type))
goto resolved;
 
if (!env_type_is_resolve_sink(env, next_type) &&
@@ -1235,7 +1242,7 @@ static int btf_ptr_resolve(struct btf_verifier_env *env,
}
 
if (!btf_type_id_size(btf, _type_id, _type_size) &&
-   !btf_type_is_void(btf_type_id_resolve(btf, _type_id))) {
+   !btf_type_nosize(btf_type_id_resolve(btf, _type_id))) {
btf_verifier_log_type(env, v->t, "Invalid type_id");
return -EINVAL;
}
@@ -1396,7 +1403,7 @@ static int btf_array_resolve(struct btf_verifier_env *env,
/* Check array->index_type */
index_type_id = array->index_type;
index_type = btf_type_by_id(btf, index_type_id);
-   if (btf_type_is_void_or_null(index_type)) {
+   if (btf_type_nosize_or_null(index_type)) {
btf_verifier_log_type(env, v->t, "Invalid index");
return -EINVAL;
}
@@ -1415,7 +1422,7 @@ static int btf_array_resolve(struct btf_verifier_env *env,
/* Check array->type */
elem_type_id = array->type;
elem_type = btf_type_by_id(btf, elem_type_id);
-   if (btf_type_is_void_or_null(elem_type)) {
+   if (btf_type_nosize_or_null(elem_type)) {
btf_verifier_log_type(env, v->t,
  "Invalid elem");
return -EINVAL;
@@ -1615,7 +1622,7 @@ static int btf_struct_resolve(struct btf_verifier_env 
*env,
const struct btf_type *member_type = btf_type_by_id(env->btf,
member_type_id);
 
-   if (btf_type_is_void_or_null(member_type)) {
+   if (btf_type_nosize_or_null(member_type)) {
btf_verifier_log_member(env, v->t, member,
"Invalid member");
return -EINVAL;
-- 
2.17.1



[PATCH bpf-next v4 07/13] tools/bpf: add new fields for program load in lib/bpf

2018-11-08 Thread Yonghong Song
The new fields are added for program load in lib/bpf so
application uses api bpf_load_program_xattr() is able
to load program with btf and func_info data.

This functionality will be used in next patch
by bpf selftest test_btf.

Acked-by: Martin KaFai Lau 
Signed-off-by: Yonghong Song 
---
 tools/lib/bpf/bpf.c | 4 
 tools/lib/bpf/bpf.h | 4 
 2 files changed, 8 insertions(+)

diff --git a/tools/lib/bpf/bpf.c b/tools/lib/bpf/bpf.c
index 03f9bcc4ef50..06fc5e91ac51 100644
--- a/tools/lib/bpf/bpf.c
+++ b/tools/lib/bpf/bpf.c
@@ -196,6 +196,10 @@ int bpf_load_program_xattr(const struct 
bpf_load_program_attr *load_attr,
attr.log_level = 0;
attr.kern_version = load_attr->kern_version;
attr.prog_ifindex = load_attr->prog_ifindex;
+   attr.prog_btf_fd = load_attr->prog_btf_fd;
+   attr.func_info_rec_size = load_attr->func_info_rec_size;
+   attr.func_info_cnt = load_attr->func_info_cnt;
+   attr.func_info = ptr_to_u64(load_attr->func_info);
memcpy(attr.prog_name, load_attr->name,
   min(name_len, BPF_OBJ_NAME_LEN - 1));
 
diff --git a/tools/lib/bpf/bpf.h b/tools/lib/bpf/bpf.h
index 26a51538213c..8bdfd806253a 100644
--- a/tools/lib/bpf/bpf.h
+++ b/tools/lib/bpf/bpf.h
@@ -74,6 +74,10 @@ struct bpf_load_program_attr {
const char *license;
__u32 kern_version;
__u32 prog_ifindex;
+   __u32 prog_btf_fd;
+   __u32 func_info_rec_size;
+   const void *func_info;
+   __u32 func_info_cnt;
 };
 
 /* Flags to direct loading requirements */
-- 
2.17.1



[PATCH bpf-next v4 02/13] bpf: btf: Add BTF_KIND_FUNC

2018-11-08 Thread Yonghong Song
This patch adds BTF_KIND_FUNC support to the type section.
BTF_KIND_FUNC is used to specify the signature of a
defined subprogram or the pointee of a function pointer.

In BTF, the function type related data structures are
  struct bpf_param {
__u32 name_off; /* parameter name */
__u32 type; /* parameter type */
  };
  struct bpf_type {
__u32 name_off; /* function name */
__u32 info; /* BTF_KIND_FUNC and num of parameters (#vlen) */
__u32 type; /* return type */
  }
The data layout of the function type:
  struct bpf_type
  #vlen number of bpf_param's

For a defined subprogram with valid function body,
  . function name and all parameter names except the vararg
must be valid C identifier.
For the pointee of a function pointer,
  . function name and all parameter names will
have name_off = 0 to indicate a non-existing name.

As a concrete example, for the C program below,
  int foo(int (*bar)(int)) { return bar(5); }
two func types will be generated:
  FuncType #1: subprogram "foo" with parameter "bar"
  FuncType #2: pointee of function pointer "int (*)(int)"

Signed-off-by: Martin KaFai Lau 
Signed-off-by: Yonghong Song 
---
 include/uapi/linux/btf.h |  17 ++-
 kernel/bpf/btf.c | 309 ++-
 2 files changed, 290 insertions(+), 36 deletions(-)

diff --git a/include/uapi/linux/btf.h b/include/uapi/linux/btf.h
index 972265f32871..9e7c74a83ee7 100644
--- a/include/uapi/linux/btf.h
+++ b/include/uapi/linux/btf.h
@@ -40,7 +40,8 @@ struct btf_type {
/* "size" is used by INT, ENUM, STRUCT and UNION.
 * "size" tells the size of the type it is describing.
 *
-* "type" is used by PTR, TYPEDEF, VOLATILE, CONST and RESTRICT.
+* "type" is used by PTR, TYPEDEF, VOLATILE, CONST, RESTRICT
+* and FUNC.
 * "type" is a type_id referring to another type.
 */
union {
@@ -64,8 +65,9 @@ struct btf_type {
 #define BTF_KIND_VOLATILE  9   /* Volatile */
 #define BTF_KIND_CONST 10  /* Const*/
 #define BTF_KIND_RESTRICT  11  /* Restrict */
-#define BTF_KIND_MAX   11
-#define NR_BTF_KINDS   12
+#define BTF_KIND_FUNC  12  /* Function */
+#define BTF_KIND_MAX   12
+#define NR_BTF_KINDS   13
 
 /* For some specific BTF_KIND, "struct btf_type" is immediately
  * followed by extra data.
@@ -110,4 +112,13 @@ struct btf_member {
__u32   offset; /* offset in bits */
 };
 
+/* BTF_KIND_FUNC is followed by multiple "struct btf_param".
+ * The exact number of btf_param is stored in the vlen (of the
+ * info in "struct btf_type").
+ */
+struct btf_param {
+   __u32   name_off;
+   __u32   type;
+};
+
 #endif /* _UAPI__LINUX_BTF_H__ */
diff --git a/kernel/bpf/btf.c b/kernel/bpf/btf.c
index 2a50d87de485..62140da0c10d 100644
--- a/kernel/bpf/btf.c
+++ b/kernel/bpf/btf.c
@@ -5,6 +5,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -259,6 +260,7 @@ static const char * const btf_kind_str[NR_BTF_KINDS] = {
[BTF_KIND_VOLATILE] = "VOLATILE",
[BTF_KIND_CONST]= "CONST",
[BTF_KIND_RESTRICT] = "RESTRICT",
+   [BTF_KIND_FUNC] = "FUNC",
 };
 
 struct btf_kind_operations {
@@ -281,6 +283,9 @@ struct btf_kind_operations {
 static const struct btf_kind_operations * const kind_ops[NR_BTF_KINDS];
 static struct btf_type btf_void;
 
+static int btf_resolve(struct btf_verifier_env *env,
+  const struct btf_type *t, u32 type_id);
+
 static bool btf_type_is_modifier(const struct btf_type *t)
 {
/* Some of them is not strictly a C modifier
@@ -314,9 +319,27 @@ static bool btf_type_is_fwd(const struct btf_type *t)
return BTF_INFO_KIND(t->info) == BTF_KIND_FWD;
 }
 
+static bool btf_type_is_func(const struct btf_type *t)
+{
+   return BTF_INFO_KIND(t->info) == BTF_KIND_FUNC;
+}
+
+static bool btf_type_is_func_prog(const struct btf_type *t)
+{
+   return BTF_INFO_KIND(t->info) == BTF_KIND_FUNC &&
+  t->name_off;
+}
+
+static bool btf_type_is_func_proto(const struct btf_type *t)
+{
+   return BTF_INFO_KIND(t->info) == BTF_KIND_FUNC &&
+  !t->name_off;
+}
+
 static bool btf_type_nosize(const struct btf_type *t)
 {
-   return btf_type_is_void(t) || btf_type_is_fwd(t);
+   return btf_type_is_void(t) || btf_type_is_fwd(t) ||
+  btf_type_is_func(t);
 }
 
 static bool btf_type_nosize_or_null(const struct btf_type *t)
@@ -433,6 +456,27 @@ static bool btf_name_offset_valid(const struct btf *btf, 
u32 offset)
offset < btf->hdr.str_len;
 }
 
+static bool btf_name_valid_identifier(const struct btf *btf, u32 offset)
+{
+   /* offset must be valid */
+

[PATCH bpf-next v4 03/13] tools/bpf: sync kernel btf.h header

2018-11-08 Thread Yonghong Song
The kernel uapi btf.h is synced to the tools directory.

Signed-off-by: Martin KaFai Lau 
Signed-off-by: Yonghong Song 
---
 tools/include/uapi/linux/btf.h | 17 ++---
 1 file changed, 14 insertions(+), 3 deletions(-)

diff --git a/tools/include/uapi/linux/btf.h b/tools/include/uapi/linux/btf.h
index 972265f32871..9e7c74a83ee7 100644
--- a/tools/include/uapi/linux/btf.h
+++ b/tools/include/uapi/linux/btf.h
@@ -40,7 +40,8 @@ struct btf_type {
/* "size" is used by INT, ENUM, STRUCT and UNION.
 * "size" tells the size of the type it is describing.
 *
-* "type" is used by PTR, TYPEDEF, VOLATILE, CONST and RESTRICT.
+* "type" is used by PTR, TYPEDEF, VOLATILE, CONST, RESTRICT
+* and FUNC.
 * "type" is a type_id referring to another type.
 */
union {
@@ -64,8 +65,9 @@ struct btf_type {
 #define BTF_KIND_VOLATILE  9   /* Volatile */
 #define BTF_KIND_CONST 10  /* Const*/
 #define BTF_KIND_RESTRICT  11  /* Restrict */
-#define BTF_KIND_MAX   11
-#define NR_BTF_KINDS   12
+#define BTF_KIND_FUNC  12  /* Function */
+#define BTF_KIND_MAX   12
+#define NR_BTF_KINDS   13
 
 /* For some specific BTF_KIND, "struct btf_type" is immediately
  * followed by extra data.
@@ -110,4 +112,13 @@ struct btf_member {
__u32   offset; /* offset in bits */
 };
 
+/* BTF_KIND_FUNC is followed by multiple "struct btf_param".
+ * The exact number of btf_param is stored in the vlen (of the
+ * info in "struct btf_type").
+ */
+struct btf_param {
+   __u32   name_off;
+   __u32   type;
+};
+
 #endif /* _UAPI__LINUX_BTF_H__ */
-- 
2.17.1



[PATCH bpf-next v4 05/13] bpf: get better bpf_prog ksyms based on btf func type_id

2018-11-08 Thread Yonghong Song
This patch added interface to load a program with the following
additional information:
   . prog_btf_fd
   . func_info, func_info_rec_size and func_info_cnt
where func_info will provide function range and type_id
corresponding to each function.

The func_info_rec_size is introduced in the UAPI to specify
struct bpf_func_info size passed from user space. This
intends to make bpf_func_info structure growable in the future.
If the kernel gets a different bpf_func_info size from userspace,
it will try to handle user request with part of bpf_func_info
it can understand. In this patch, kernel can understand
  struct bpf_func_info {
   __u32   insn_offset;
   __u32   type_id;
  };
If user passed a bpf func_info record size of 16 bytes, the
kernel can still handle part of records with the above definition.

If verifier agrees with function range provided by the user,
the bpf_prog ksym for each function will use the func name
provided in the type_id, which is supposed to provide better
encoding as it is not limited by 16 bytes program name
limitation and this is better for bpf program which contains
multiple subprograms.

The bpf_prog_info interface is also extended to
return btf_id, func_info, func_info_rec_size and func_info_cnt
to userspace, so userspace can print out the function prototype
for each xlated function. The insn_offset in the returned
func_info corresponds to the insn offset for xlated functions.
With other jit related fields in bpf_prog_info, userspace can also
print out function prototypes for each jited function.

Acked-by: Martin KaFai Lau 
Signed-off-by: Yonghong Song 
---
 include/linux/bpf.h  |   5 +-
 include/linux/bpf_verifier.h |   1 +
 include/linux/btf.h  |   2 +
 include/uapi/linux/bpf.h |  13 
 kernel/bpf/btf.c |   4 +-
 kernel/bpf/core.c|  13 
 kernel/bpf/syscall.c |  59 +++--
 kernel/bpf/verifier.c| 121 ++-
 8 files changed, 210 insertions(+), 8 deletions(-)

diff --git a/include/linux/bpf.h b/include/linux/bpf.h
index 33014ae73103..5835aa70e301 100644
--- a/include/linux/bpf.h
+++ b/include/linux/bpf.h
@@ -312,6 +312,8 @@ struct bpf_prog_aux {
void *security;
 #endif
struct bpf_prog_offload *offload;
+   struct btf *btf;
+   u32 type_id; /* type id for this prog/func */
union {
struct work_struct work;
struct rcu_head rcu;
@@ -523,7 +525,8 @@ static inline void bpf_long_memcpy(void *dst, const void 
*src, u32 size)
 }
 
 /* verify correctness of eBPF program */
-int bpf_check(struct bpf_prog **fp, union bpf_attr *attr);
+int bpf_check(struct bpf_prog **fp, union bpf_attr *attr,
+ union bpf_attr __user *uattr);
 void bpf_patch_call_args(struct bpf_insn *insn, u32 stack_depth);
 
 /* Map specifics */
diff --git a/include/linux/bpf_verifier.h b/include/linux/bpf_verifier.h
index d93e89761a8b..7f52528e6a06 100644
--- a/include/linux/bpf_verifier.h
+++ b/include/linux/bpf_verifier.h
@@ -204,6 +204,7 @@ static inline bool bpf_verifier_log_needed(const struct 
bpf_verifier_log *log)
 struct bpf_subprog_info {
u32 start; /* insn idx of function entry point */
u16 stack_depth; /* max. stack depth used by this function */
+   u32 type_id; /* btf type_id for this subprog */
 };
 
 /* single container for all structs
diff --git a/include/linux/btf.h b/include/linux/btf.h
index e076c4697049..7f2c0a4a45ea 100644
--- a/include/linux/btf.h
+++ b/include/linux/btf.h
@@ -46,5 +46,7 @@ void btf_type_seq_show(const struct btf *btf, u32 type_id, 
void *obj,
   struct seq_file *m);
 int btf_get_fd_by_id(u32 id);
 u32 btf_id(const struct btf *btf);
+const struct btf_type *btf_type_by_id(const struct btf *btf, u32 type_id);
+const char *btf_name_by_offset(const struct btf *btf, u32 offset);
 
 #endif
diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h
index 852dc17ab47a..28db552a1eed 100644
--- a/include/uapi/linux/bpf.h
+++ b/include/uapi/linux/bpf.h
@@ -335,6 +335,10 @@ union bpf_attr {
 * (context accesses, allowed helpers, etc).
 */
__u32   expected_attach_type;
+   __u32   prog_btf_fd;/* fd pointing to BTF type data 
*/
+   __u32   func_info_rec_size; /* userspace 
bpf_func_info size */
+   __aligned_u64   func_info;  /* func info */
+   __u32   func_info_cnt;  /* number of bpf_func_info 
records */
};
 
struct { /* anonymous struct used by BPF_OBJ_* commands */
@@ -2631,6 +2635,10 @@ struct bpf_prog_info {
__u32 nr_jited_func_lens;
__aligned_u64 jited_ksyms;
__aligned_u64 jited_func_lens;
+   __u32 btf_id;
+   __u32 func_info_rec_size;
+   __aligned_u64 func_info;
+   __u32 func_info_cnt;
 } __attribute__((aligned(8)));
 
 struct bpf_map_info {
@@ -2942,4

[PATCH bpf-next v4 00/13] bpf: add btf func info support

2018-11-08 Thread Yonghong Song
The BTF support was added to kernel by Commit 69b693f0aefa
("bpf: btf: Introduce BPF Type Format (BTF)"), which introduced
.BTF section into ELF file and is primarily
used for map pretty print.
pahole is used to convert dwarf to BTF for ELF files.

This patch added func info support to the kernel so we can
get better ksym's for bpf function calls. Basically,
function call types are passed to kernel and the kernel
extract function names from these types in order to contruct ksym
for these functions.

The llvm patch at https://reviews.llvm.org/D53736
will generate .BTF section and one more section .BTF.ext.
The .BTF.ext section encodes function type
information. The following is a sample output for selftests
test_btf with file test_btf_haskv.o for translated insns
and jited insns respectively.

  $ bpftool prog dump xlated id 1
  int _dummy_tracepoint(struct dummy_tracepoint_args * arg):
 0: (85) call pc+2#bpf_prog_2dcecc18072623fc_test_long_fname_1
 1: (b7) r0 = 0
 2: (95) exit
  int test_long_fname_1(struct dummy_tracepoint_args * arg):
 3: (85) call pc+1#bpf_prog_89d64e4abf0f0126_test_long_fname_2
 4: (95) exit
  int test_long_fname_2(struct dummy_tracepoint_args * arg):
 5: (b7) r2 = 0
 6: (63) *(u32 *)(r10 -4) = r2
 7: (79) r1 = *(u64 *)(r1 +8)
 ...
 22: (07) r1 += 1
 23: (63) *(u32 *)(r0 +4) = r1
 24: (95) exit

  $ bpftool prog dump jited id 1
  int _dummy_tracepoint(struct dummy_tracepoint_args * arg):
  bpf_prog_b07ccb89267cf242__dummy_tracepoint:
 0:   push   %rbp
 1:   mov%rsp,%rbp
..
3c:   add$0x28,%rbp
40:   leaveq
41:   retq

  int test_long_fname_1(struct dummy_tracepoint_args * arg):
  bpf_prog_2dcecc18072623fc_test_long_fname_1:
 0:   push   %rbp
 1:   mov%rsp,%rbp
..
3a:   add$0x28,%rbp
3e:   leaveq
3f:   retq

  int test_long_fname_2(struct dummy_tracepoint_args * arg):
  bpf_prog_89d64e4abf0f0126_test_long_fname_2:
 0:   push   %rbp
 1:   mov%rsp,%rbp
..
80:   add$0x28,%rbp
84:   leaveq
85:   retq

For the patchset,
Patch #1  refactors the code to break up btf_type_is_void().
Patch #2  introduces new BTF type BTF_KIND_FUNC.
Patch #3  syncs btf.h header to tools directory.
Patch #4  adds btf func type self tests in test_btf.
Patch #5  adds kernel interface to load func_info to kernel
  and pass func_info back to userspace.
Patch #6  syncs bpf.h header to tools directory.
Patch #7  adds news btf/func_info related fields in libbpf
  program load function.
Patch #8  extends selftest test_btf to test load/retrieve func_info.
Patch #9  adds .BTF.ext func info support.
Patch #10 changes Makefile to avoid using pahole if llvm is capable of
  generating BTF sections.
Patch #11 refactors to have btf_get_from_id() in libbpf for reuse.
Patch #12 enhance test_btf file testing to test func info.
Patch #13 adds bpftool support for func signature dump.

Changelogs:
  v3 -> v4:
. Remove BTF_KIND_FUNC_PROTO. BTF_KIND_FUNC is used for
  both function pointer and subprogram. The name_off field
  is used to distinguish both.
. The record size is added to the func_info subsection
  in .BTF.ext to enable future extension.
. The bpf_prog_info interface change to make it similar
  bpf_prog_load.
. Related kernel and libbpf changes to accommodate the
  new .BTF.ext and kernel interface changes.
  v2 -> v3:
. Removed kernel btf extern functions btf_type_id_func()
  and btf_get_name_by_id(). Instead, exposing existing
  functions btf_type_by_id() and btf_name_by_offset().
. Added comments about ELF section .BTF.ext layout.
. Better codes in btftool as suggested by Edward Cree.
  v1 -> v2:
. Added missing sign-off.
. Limited the func_name/struct_member_name length for validity test.
. Removed/changed several verifier messages.
. Modified several commit messages to remove line_off reference.

Yonghong Song (13):
  bpf: btf: Break up btf_type_is_void()
  bpf: btf: Add BTF_KIND_FUNC
  tools/bpf: sync kernel btf.h header
  tools/bpf: add btf func unit tests in selftest test_btf
  bpf: get better bpf_prog ksyms based on btf func type_id
  tools/bpf: sync kernel uapi bpf.h header to tools directory
  tools/bpf: add new fields for program load in lib/bpf
  tools/bpf: extends test_btf to test load/retrieve func_type info
  tools/bpf: add support to read .BTF.ext sections
  tools/bpf: do not use pahole if clang/llvm can generate BTF sections
  tools/bpf: refactor to implement btf_get_from_id() in lib/bpf
  tools/bpf: enhance test_btf file testing to test func info
  tools/bpf: bpftool: add support for func types

 include/linux/bpf.h  |   5 +-
 include/linux/bpf_verifier.h |   1 +
 include/linux/btf.h  |   2 +
 include/uapi/linux/bpf.h |  13 +
 inclu

[PATCH bpf v2] tools/bpftool: copy a few net uapi headers to tools directory

2018-11-07 Thread Yonghong Song
Commit f6f3bac08ff9 ("tools/bpf: bpftool: add net support")
added certain networking support to bpftool.
The implementation relies on a relatively recent uapi header file
linux/tc_act/tc_bpf.h on the host which contains the marco
definition of TCA_ACT_BPF_ID.

Unfortunately, this is not the case for all distributions.
See the email message below where rhel-7.2 does not have
an up-to-date linux/tc_act/tc_bpf.h.
  https://www.mail-archive.com/linux-kernel@vger.kernel.org/msg1799211.html
Further investigation found that linux/pkt_cls.h is also needed for macro
TCA_BPF_TAG.

This patch fixed the issue by copying linux/tc_act/tc_bpf.h
and linux/pkt_cls.h from kernel include/uapi directory to
tools/include/uapi directory so building the bpftool does not depend
on host system for these files.

Fixes: f6f3bac08ff9 ("tools/bpf: bpftool: add net support")
Reported-by: kernel test robot 
Cc: Li Zhijian 
Signed-off-by: Yonghong Song 
---
 tools/include/uapi/linux/pkt_cls.h   | 612 +++
 tools/include/uapi/linux/tc_act/tc_bpf.h |  37 ++
 2 files changed, 649 insertions(+)
 create mode 100644 tools/include/uapi/linux/pkt_cls.h
 create mode 100644 tools/include/uapi/linux/tc_act/tc_bpf.h

Changelogs:
  v1 -> v2:
. copy linux/pkt_cls.h as well.

diff --git a/tools/include/uapi/linux/pkt_cls.h 
b/tools/include/uapi/linux/pkt_cls.h
new file mode 100644
index ..401d0c1e612d
--- /dev/null
+++ b/tools/include/uapi/linux/pkt_cls.h
@@ -0,0 +1,612 @@
+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
+#ifndef __LINUX_PKT_CLS_H
+#define __LINUX_PKT_CLS_H
+
+#include 
+#include 
+
+#define TC_COOKIE_MAX_SIZE 16
+
+/* Action attributes */
+enum {
+   TCA_ACT_UNSPEC,
+   TCA_ACT_KIND,
+   TCA_ACT_OPTIONS,
+   TCA_ACT_INDEX,
+   TCA_ACT_STATS,
+   TCA_ACT_PAD,
+   TCA_ACT_COOKIE,
+   __TCA_ACT_MAX
+};
+
+#define TCA_ACT_MAX __TCA_ACT_MAX
+#define TCA_OLD_COMPAT (TCA_ACT_MAX+1)
+#define TCA_ACT_MAX_PRIO 32
+#define TCA_ACT_BIND   1
+#define TCA_ACT_NOBIND 0
+#define TCA_ACT_UNBIND 1
+#define TCA_ACT_NOUNBIND   0
+#define TCA_ACT_REPLACE1
+#define TCA_ACT_NOREPLACE  0
+
+#define TC_ACT_UNSPEC  (-1)
+#define TC_ACT_OK  0
+#define TC_ACT_RECLASSIFY  1
+#define TC_ACT_SHOT2
+#define TC_ACT_PIPE3
+#define TC_ACT_STOLEN  4
+#define TC_ACT_QUEUED  5
+#define TC_ACT_REPEAT  6
+#define TC_ACT_REDIRECT7
+#define TC_ACT_TRAP8 /* For hw path, this means "trap to cpu"
+  * and don't further process the frame
+  * in hardware. For sw path, this is
+  * equivalent of TC_ACT_STOLEN - drop
+  * the skb and act like everything
+  * is alright.
+  */
+#define TC_ACT_VALUE_MAX   TC_ACT_TRAP
+
+/* There is a special kind of actions called "extended actions",
+ * which need a value parameter. These have a local opcode located in
+ * the highest nibble, starting from 1. The rest of the bits
+ * are used to carry the value. These two parts together make
+ * a combined opcode.
+ */
+#define __TC_ACT_EXT_SHIFT 28
+#define __TC_ACT_EXT(local) ((local) << __TC_ACT_EXT_SHIFT)
+#define TC_ACT_EXT_VAL_MASK ((1 << __TC_ACT_EXT_SHIFT) - 1)
+#define TC_ACT_EXT_OPCODE(combined) ((combined) & (~TC_ACT_EXT_VAL_MASK))
+#define TC_ACT_EXT_CMP(combined, opcode) (TC_ACT_EXT_OPCODE(combined) == 
opcode)
+
+#define TC_ACT_JUMP __TC_ACT_EXT(1)
+#define TC_ACT_GOTO_CHAIN __TC_ACT_EXT(2)
+#define TC_ACT_EXT_OPCODE_MAX  TC_ACT_GOTO_CHAIN
+
+/* Action type identifiers*/
+enum {
+   TCA_ID_UNSPEC=0,
+   TCA_ID_POLICE=1,
+   /* other actions go here */
+   __TCA_ID_MAX=255
+};
+
+#define TCA_ID_MAX __TCA_ID_MAX
+
+struct tc_police {
+   __u32   index;
+   int action;
+#define TC_POLICE_UNSPEC   TC_ACT_UNSPEC
+#define TC_POLICE_OK   TC_ACT_OK
+#define TC_POLICE_RECLASSIFY   TC_ACT_RECLASSIFY
+#define TC_POLICE_SHOT TC_ACT_SHOT
+#define TC_POLICE_PIPE TC_ACT_PIPE
+
+   __u32   limit;
+   __u32   burst;
+   __u32   mtu;
+   struct tc_ratespec  rate;
+   struct tc_ratespec  peakrate;
+   int refcnt;
+   int bindcnt;
+   __u32   capab;
+};
+
+struct tcf_t {
+   __u64   install;
+   __u64   lastuse;
+   __u64   expires;
+   __u64   firstuse;
+};
+
+struct tc_cnt {
+   int   refcnt;
+   int   bindcnt;
+};
+
+#define tc_gen \
+   __u32 index; \
+   __u32 capab; \
+   int   action; \
+   int   

Re: [PATCH bpf] tools/bpftool: copy uapi/linux/tc_act/tc_bpf.h to tools directory

2018-11-07 Thread Yonghong Song


On 11/7/18 5:15 PM, Li Zhijian wrote:
> On 11/8/2018 9:00 AM, Yonghong Song wrote:
>> Commit f6f3bac08ff9 ("tools/bpf: bpftool: add net support")
>> added certain networking support to bpftool.
>> The implementation relies on a relatively recent uapi header file
>> linux/tc_act/tc_bpf.h on the host which contains the marco
>> definition of TCA_ACT_BPF_ID.
>>
>> Unfortunately, this is not the case for all distributions.
>> See the email message below where rhel-7.2 does not have
>> an up-to-date linux/tc_act/tc_bpf.h.
>>
>> https://urldefense.proofpoint.com/v2/url?u=https-3A__www.mail-2Darchive.com_linux-2Dkernel-40vger.kernel.org_msg1799211.html=DwICaQ=5VD0RTtNlTh3ycd41b3MUw=DA8e1B5r073vIqRrFz7MRA=BQIJZUzQfMmUkyvlAHMs7zygIFBysR_MlkAyHN59-7E=pVed3MjGDG_PMeBrhrqb3m57NRinnlcdL1QjAOj4iLA=
>>  
>>
> 
> i have not tested this patch, but basing on the early commit
> 6f3bac08ff9 ("tools/bpf: bpftool: add net support")
> i cooked up similar patch locally, but i noticed that it also requires an
> up-to-date linux/pkt_cls.h as well to avoid compiling errors:

Thanks for testing. I will add linux/pkt_cls.h as well for the
version 2.

> 
> root@lkp-bdw-ep3 ~/linux-f6f3bac08f/tools/bpf/bpftool# make V=1
> [...snip...]
> gcc -O2 -W -Wall -Wextra -Wno-unused-parameter -Wshadow 
> -Wno-missing-field-initializers -DPACKAGE='"bpftool"' 
> -D__EXPORTED_HEADERS__ -I/root/linux-f6f3bac08f/kernel/bpf/ 
> -I/root/linux-f6f3bac08f/tools/include 
> -I/root/linux-f6f3bac08f/tools/include/uapi 
> -I/root/linux-f6f3bac08f/tools/lib/bpf 
> -I/root/linux-f6f3bac08f/tools/perf -DBPFTOOL_VERSION='"4.19.0-rc2"' 
> -DCOMPAT_NEED_REALLOCARRAY   -c -MMD -o netlink_dumper.o netlink_dumper.c
> make -C /root/linux-f6f3bac08f/tools/lib/bpf/ OUTPUT= libbpf.a
> make[1]: Entering directory '/root/linux-f6f3bac08f/tools/lib/bpf'
> netlink_dumper.c: In function 'do_bpf_filter_dump':
> netlink_dumper.c:153:9: error: 'TCA_BPF_ID' undeclared (first use in 
> this function)
>    if (tb[TCA_BPF_ID])
>   ^~
> netlink_dumper.c:153:9: note: each undeclared identifier is reported 
> only once for each function it appears in
> netlink_dumper.c:155:9: error: 'TCA_BPF_TAG' undeclared (first use in 
> this function)
>    if (tb[TCA_BPF_TAG])
>   ^~~
> Makefile:96: recipe for target 'netlink_dumper.o' failed
> make: *** [netlink_dumper.o] Error 1
> make: *** Waiting for unfinished jobs
> make -f /root/linux-f6f3bac08f/tools/build/Makefile.build dir=. obj=libbpf
> make[1]: Leaving directory '/root/linux-f6f3bac08f/tools/lib/bpf'
> 
> Thanks
> Zhijian
> 
>>
>> This patch fixed the issue by copying linux/tc_act/tc_bpf.h from
>> kernel include/uapi directory to tools/include/uapi directory so
>> building the bpftool does not depend on host system for this file.
>>
>> Fixes: f6f3bac08ff9 ("tools/bpf: bpftool: add net support")
>> Reported-by: kernel test robot 
>> Signed-off-by: Yonghong Song 
>> ---
>>   tools/include/uapi/linux/tc_act/tc_bpf.h | 37 
>>   1 file changed, 37 insertions(+)
>>   create mode 100644 tools/include/uapi/linux/tc_act/tc_bpf.h
>>
>> diff --git a/tools/include/uapi/linux/tc_act/tc_bpf.h 
>> b/tools/include/uapi/linux/tc_act/tc_bpf.h
>> new file mode 100644
>> index ..6e89a5df49a4
>> --- /dev/null
>> +++ b/tools/include/uapi/linux/tc_act/tc_bpf.h
>> @@ -0,0 +1,37 @@
>> +/* SPDX-License-Identifier: GPL-2.0+ WITH Linux-syscall-note */
>> +/*
>> + * Copyright (c) 2015 Jiri Pirko 
>> + *
>> + * This program is free software; you can redistribute it and/or modify
>> + * it under the terms of the GNU General Public License as published by
>> + * the Free Software Foundation; either version 2 of the License, or
>> + * (at your option) any later version.
>> + */
>> +
>> +#ifndef __LINUX_TC_BPF_H
>> +#define __LINUX_TC_BPF_H
>> +
>> +#include 
>> +
>> +#define TCA_ACT_BPF 13
>> +
>> +struct tc_act_bpf {
>> +    tc_gen;
>> +};
>> +
>> +enum {
>> +    TCA_ACT_BPF_UNSPEC,
>> +    TCA_ACT_BPF_TM,
>> +    TCA_ACT_BPF_PARMS,
>> +    TCA_ACT_BPF_OPS_LEN,
>> +    TCA_ACT_BPF_OPS,
>> +    TCA_ACT_BPF_FD,
>> +    TCA_ACT_BPF_NAME,
>> +    TCA_ACT_BPF_PAD,
>> +    TCA_ACT_BPF_TAG,
>> +    TCA_ACT_BPF_ID,
>> +    __TCA_ACT_BPF_MAX,
>> +};
>> +#define TCA_ACT_BPF_MAX (__TCA_ACT_BPF_MAX - 1)
>> +
>> +#endif


[PATCH bpf] tools/bpftool: copy uapi/linux/tc_act/tc_bpf.h to tools directory

2018-11-07 Thread Yonghong Song
Commit f6f3bac08ff9 ("tools/bpf: bpftool: add net support")
added certain networking support to bpftool.
The implementation relies on a relatively recent uapi header file
linux/tc_act/tc_bpf.h on the host which contains the marco
definition of TCA_ACT_BPF_ID.

Unfortunately, this is not the case for all distributions.
See the email message below where rhel-7.2 does not have
an up-to-date linux/tc_act/tc_bpf.h.
  https://www.mail-archive.com/linux-kernel@vger.kernel.org/msg1799211.html

This patch fixed the issue by copying linux/tc_act/tc_bpf.h from
kernel include/uapi directory to tools/include/uapi directory so
building the bpftool does not depend on host system for this file.

Fixes: f6f3bac08ff9 ("tools/bpf: bpftool: add net support")
Reported-by: kernel test robot 
Signed-off-by: Yonghong Song 
---
 tools/include/uapi/linux/tc_act/tc_bpf.h | 37 
 1 file changed, 37 insertions(+)
 create mode 100644 tools/include/uapi/linux/tc_act/tc_bpf.h

diff --git a/tools/include/uapi/linux/tc_act/tc_bpf.h 
b/tools/include/uapi/linux/tc_act/tc_bpf.h
new file mode 100644
index ..6e89a5df49a4
--- /dev/null
+++ b/tools/include/uapi/linux/tc_act/tc_bpf.h
@@ -0,0 +1,37 @@
+/* SPDX-License-Identifier: GPL-2.0+ WITH Linux-syscall-note */
+/*
+ * Copyright (c) 2015 Jiri Pirko 
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#ifndef __LINUX_TC_BPF_H
+#define __LINUX_TC_BPF_H
+
+#include 
+
+#define TCA_ACT_BPF 13
+
+struct tc_act_bpf {
+   tc_gen;
+};
+
+enum {
+   TCA_ACT_BPF_UNSPEC,
+   TCA_ACT_BPF_TM,
+   TCA_ACT_BPF_PARMS,
+   TCA_ACT_BPF_OPS_LEN,
+   TCA_ACT_BPF_OPS,
+   TCA_ACT_BPF_FD,
+   TCA_ACT_BPF_NAME,
+   TCA_ACT_BPF_PAD,
+   TCA_ACT_BPF_TAG,
+   TCA_ACT_BPF_ID,
+   __TCA_ACT_BPF_MAX,
+};
+#define TCA_ACT_BPF_MAX (__TCA_ACT_BPF_MAX - 1)
+
+#endif
-- 
2.17.1



Re: Help with the BPF verifier

2018-11-02 Thread Yonghong Song


On 11/2/18 8:42 AM, Edward Cree wrote:
> On 02/11/18 15:02, Arnaldo Carvalho de Melo wrote:
>> Yeah, didn't work as well:
> 
>> And the -vv in 'perf trace' didn't seem to map to further details in the
>> output of the verifier debug:
> Yeah for log_level 2 you probably need to make source-level changes to either
>   perf or libbpf (I think the latter).  It's annoying that essentially no 
> tools
>   plumb through an option for that, someone should fix them ;-)
> 
>> libbpf: -- BEGIN DUMP LOG ---
>> libbpf:
>> 0: (bf) r6 = r1
>> 1: (bf) r1 = r10
>> 2: (07) r1 += -328
>> 3: (b7) r7 = 64
>> 4: (b7) r2 = 64
>> 5: (bf) r3 = r6
>> 6: (85) call bpf_probe_read#4
>> 7: (79) r1 = *(u64 *)(r10 -320)
>> 8: (15) if r1 == 0x101 goto pc+4
>>   R0=inv(id=0) R1=inv(id=0) R6=ctx(id=0,off=0,imm=0) R7=inv64 R10=fp0,call_-1
>> 9: (55) if r1 != 0x2 goto pc+22
>>   R0=inv(id=0) R1=inv2 R6=ctx(id=0,off=0,imm=0) R7=inv64 R10=fp0,call_-1
>> 10: (bf) r1 = r6
>> 11: (07) r1 += 16
>> 12: (05) goto pc+2
>> 15: (79) r3 = *(u64 *)(r1 +0)
>> dereference of modified ctx ptr R1 off=16 disallowed
> Aha, we at least got a different error message this time.
> And indeed llvm has done that optimisation, rather than the more obvious
> 11: r3 = *(u64 *)(r1 +16)
>   because it wants to have lots of reads share a single insn.  You may be able
>   to defeat that optimisation by adding compiler barriers, idk.  Maybe someone
>   with llvm knowledge can figure out how to stop it (ideally, llvm would know
>   when it's generating for bpf backend and not do that).  -O0?  ¯\_(ツ)_/¯

The optimization mostly likes below:
br1:
  ...
  r1 += 16
  goto merge
br2:
  ...
  r1 += 20
  goto merge
merge:
  *(u64 *)(r1 + 0)

The compiler tries to merge common loads. There is no easy way to
stop this compiler optimization without turning off a lot of other
optimizations. The easiest way is to add barriers
__asm__ __volatile__("": : :"memory")
after the ctx memory access to prevent their down stream merging.

> Alternatively, your prog looks short enough that maybe you could kick the C
>   habit and write it directly in eBPF asm, that way no-one is optimising 
> things
>   behind your back.  (I realise this option won't appeal to everyone ;-)

The LLVM supports BPF inline assembly as well. Some examples here
https://github.com/llvm-mirror/llvm/blob/master/test/CodeGen/BPF/inline_asm.ll
You may try it for selective ctx access to work around some
compiler optimizations. I personally have not used it yet and actually
not sure whether it actually works or not :-)

> The reason the verifier disallows this, iirc, is because it needs to be able
>   to rewrite the offsets on ctx accesses (see convert_ctx_accesses()) in case 
> >   underlying kernel struct doesn't match the layout of the ctx ABI.  
To do this
>   it needs the ctx offset to live entirely in the insn doing the access,
>   otherwise different paths could lead to the same insn accessing different 
> ctx
>   offsets with different fixups needed — can't be done.
> 
> -Ed
> 


[PATCH iproute2] bpf: check map symbol type properly with newer llvm compiler

2018-10-29 Thread Yonghong Song
With llvm 7.0 or earlier, the map symbol type is STT_NOTYPE.
  -bash-4.4$ cat t.c
  __attribute__((section("maps"))) int g;
  -bash-4.4$ clang -target bpf -O2 -c t.c
  -bash-4.4$ readelf -s t.o

  Symbol table '.symtab' contains 2 entries:
 Num:Value  Size TypeBind   Vis  Ndx Name
   0:  0 NOTYPE  LOCAL  DEFAULT  UND
   1:  0 NOTYPE  GLOBAL DEFAULT3 g
  -bash-4.4$

The following llvm commit enables BPF target to generate
proper symbol type and size.
  commit bf6ec206615b9718869d48b4e5400d0c6e3638dd
  Author: Yonghong Song 
  Date:   Wed Sep 19 16:04:13 2018 +

  [bpf] Symbol sizes and types in object file

  Clang-compiled object files currently don't include the symbol sizes and
  types.  Some tools however need that information.  For example, ctfconvert
  uses that information to generate FreeBSD's CTF representation from ELF
  files.
  With this patch, symbol sizes and types are included in object files.

  Signed-off-by: Paul Chaignon 
  Reported-by: Yutaro Hayakawa 

Hence, for llvm 8.0.0 (currently trunk), symbol type will be not NOTYPE, but 
OBJECT.
  -bash-4.4$ clang -target bpf -O2 -c t.c
  -bash-4.4$ readelf -s t.o

  Symbol table '.symtab' contains 3 entries:
 Num:Value  Size TypeBind   Vis  Ndx Name
   0:  0 NOTYPE  LOCAL  DEFAULT  UND
   1:  0 FILELOCAL  DEFAULT  ABS t.c
   2:  4 OBJECT  GLOBAL DEFAULT3 g
-bash-4.4$

This patch makes sure bpf library accepts both NOTYPE and OBJECT types
of global map symbols.

Signed-off-by: Yonghong Song 
---
 lib/bpf.c | 12 +---
 1 file changed, 9 insertions(+), 3 deletions(-)

diff --git a/lib/bpf.c b/lib/bpf.c
index d093d0bd..45f279fa 100644
--- a/lib/bpf.c
+++ b/lib/bpf.c
@@ -1758,11 +1758,13 @@ static const char *bpf_map_fetch_name(struct 
bpf_elf_ctx *ctx, int which)
int i;
 
for (i = 0; i < ctx->sym_num; i++) {
+   int type = GELF_ST_TYPE(sym.st_info);
+
if (gelf_getsym(ctx->sym_tab, i, ) != )
continue;
 
if (GELF_ST_BIND(sym.st_info) != STB_GLOBAL ||
-   GELF_ST_TYPE(sym.st_info) != STT_NOTYPE ||
+   (type != STT_NOTYPE && type != STT_OBJECT) ||
sym.st_shndx != ctx->sec_maps ||
sym.st_value / ctx->map_len != which)
continue;
@@ -1849,11 +1851,13 @@ static int bpf_map_num_sym(struct bpf_elf_ctx *ctx)
GElf_Sym sym;
 
for (i = 0; i < ctx->sym_num; i++) {
+   int type = GELF_ST_TYPE(sym.st_info);
+
if (gelf_getsym(ctx->sym_tab, i, ) != )
continue;
 
if (GELF_ST_BIND(sym.st_info) != STB_GLOBAL ||
-   GELF_ST_TYPE(sym.st_info) != STT_NOTYPE ||
+   (type != STT_NOTYPE && type != STT_OBJECT) ||
sym.st_shndx != ctx->sec_maps)
continue;
num++;
@@ -1927,10 +1931,12 @@ static int bpf_map_verify_all_offs(struct bpf_elf_ctx 
*ctx, int end)
 * the table again.
 */
for (i = 0; i < ctx->sym_num; i++) {
+   int type = GELF_ST_TYPE(sym.st_info);
+
if (gelf_getsym(ctx->sym_tab, i, ) != )
continue;
if (GELF_ST_BIND(sym.st_info) != STB_GLOBAL ||
-   GELF_ST_TYPE(sym.st_info) != STT_NOTYPE ||
+   (type != STT_NOTYPE && type != STT_OBJECT) ||
sym.st_shndx != ctx->sec_maps)
continue;
if (sym.st_value == off)
-- 
2.17.1



[PATCH bpf] tools/bpf: add unlimited rlimit for flow_dissector_load

2018-10-29 Thread Yonghong Song
On our test machine, bpf selftest test_flow_dissector.sh failed
with the following error:
  # ./test_flow_dissector.sh
  bpffs not mounted. Mounting...
  libbpf: failed to create map (name: 'jmp_table'): Operation not permitted
  libbpf: failed to load object 'bpf_flow.o'
  ./flow_dissector_load: bpf_prog_load bpf_flow.o
  selftests: test_flow_dissector [FAILED]

Let us increase the rlimit to remove the above map
creation failure.

Signed-off-by: Yonghong Song 
---
 tools/testing/selftests/bpf/flow_dissector_load.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/tools/testing/selftests/bpf/flow_dissector_load.c 
b/tools/testing/selftests/bpf/flow_dissector_load.c
index d3273b5b3173..ae8180b11d5f 100644
--- a/tools/testing/selftests/bpf/flow_dissector_load.c
+++ b/tools/testing/selftests/bpf/flow_dissector_load.c
@@ -11,6 +11,8 @@
 #include 
 #include 
 
+#include "bpf_rlimit.h"
+
 const char *cfg_pin_path = "/sys/fs/bpf/flow_dissector";
 const char *cfg_map_name = "jmp_table";
 bool cfg_attach = true;
-- 
2.17.1



[PATCH bpf-next v3 13/13] tools/bpf: bpftool: add support for jited func types

2018-10-17 Thread Yonghong Song
This patch added support to print function signature
if btf func_info is available. Note that ksym
now uses function name instead of prog_name as
prog_name has a limit of 16 bytes including
ending '\0'.

The following is a sample output for selftests
test_btf with file test_btf_haskv.o:

  $ bpftool prog dump jited id 1
  int _dummy_tracepoint(struct dummy_tracepoint_args * ):
  bpf_prog_b07ccb89267cf242__dummy_tracepoint:
 0:   push   %rbp
 1:   mov%rsp,%rbp
..
3c:   add$0x28,%rbp
40:   leaveq
41:   retq

  int test_long_fname_1(struct dummy_tracepoint_args * ):
  bpf_prog_2dcecc18072623fc_test_long_fname_1:
 0:   push   %rbp
 1:   mov%rsp,%rbp
..
3a:   add$0x28,%rbp
3e:   leaveq
3f:   retq

  int test_long_fname_2(struct dummy_tracepoint_args * ):
  bpf_prog_89d64e4abf0f0126_test_long_fname_2:
 0:   push   %rbp
 1:   mov%rsp,%rbp
..
80:   add$0x28,%rbp
84:   leaveq
85:   retq

Signed-off-by: Yonghong Song 
---
 tools/bpf/bpftool/btf_dumper.c | 90 ++
 tools/bpf/bpftool/main.h   |  2 +
 tools/bpf/bpftool/prog.c   | 54 
 3 files changed, 146 insertions(+)

diff --git a/tools/bpf/bpftool/btf_dumper.c b/tools/bpf/bpftool/btf_dumper.c
index 55bc512a1831..6122b735ddcc 100644
--- a/tools/bpf/bpftool/btf_dumper.c
+++ b/tools/bpf/bpftool/btf_dumper.c
@@ -249,3 +249,93 @@ int btf_dumper_type(const struct btf_dumper *d, __u32 
type_id,
 {
return btf_dumper_do_type(d, type_id, 0, data);
 }
+
+#define BTF_PRINT_ARG(...) \
+   do {\
+   pos += snprintf(func_sig + pos, size - pos, \
+   __VA_ARGS__);   \
+   if (pos >= size)\
+   return -1;  \
+   } while (0)
+#define BTF_PRINT_TYPE(type)   \
+   do {\
+   pos = __btf_dumper_type_only(btf, type, func_sig,   \
+pos, size);\
+   if (pos == -1)  \
+   return -1;  \
+   } while (0)
+
+static int __btf_dumper_type_only(struct btf *btf, __u32 type_id,
+ char *func_sig, int pos, int size)
+{
+   const struct btf_type *t = btf__type_by_id(btf, type_id);
+   const struct btf_array *array;
+   int i, vlen;
+
+   switch (BTF_INFO_KIND(t->info)) {
+   case BTF_KIND_INT:
+   BTF_PRINT_ARG("%s ", btf__name_by_offset(btf, t->name_off));
+   break;
+   case BTF_KIND_STRUCT:
+   BTF_PRINT_ARG("struct %s ",
+ btf__name_by_offset(btf, t->name_off));
+   break;
+   case BTF_KIND_UNION:
+   BTF_PRINT_ARG("union %s ",
+ btf__name_by_offset(btf, t->name_off));
+   break;
+   case BTF_KIND_ENUM:
+   BTF_PRINT_ARG("enum %s ",
+ btf__name_by_offset(btf, t->name_off));
+   break;
+   case BTF_KIND_ARRAY:
+   array = (struct btf_array *)(t + 1);
+   BTF_PRINT_TYPE(array->type);
+   BTF_PRINT_ARG("[%d]", array->nelems);
+   break;
+   case BTF_KIND_PTR:
+   BTF_PRINT_TYPE(t->type);
+   BTF_PRINT_ARG("* ");
+   break;
+   case BTF_KIND_UNKN:
+   case BTF_KIND_FWD:
+   case BTF_KIND_TYPEDEF:
+   return -1;
+   case BTF_KIND_VOLATILE:
+   BTF_PRINT_ARG("volatile ");
+   BTF_PRINT_TYPE(t->type);
+   break;
+   case BTF_KIND_CONST:
+   BTF_PRINT_ARG("const ");
+   BTF_PRINT_TYPE(t->type);
+   break;
+   case BTF_KIND_RESTRICT:
+   BTF_PRINT_ARG("restrict ");
+   BTF_PRINT_TYPE(t->type);
+   break;
+   case BTF_KIND_FUNC:
+   case BTF_KIND_FUNC_PROTO:
+   BTF_PRINT_TYPE(t->type);
+   BTF_PRINT_ARG("%s(", btf__name_by_offset(btf, t->name_off));
+   vlen = BTF_INFO_VLEN(t->info);
+   for (i = 0; i < vlen; i++) {
+   __u32 arg_type = ((__u32 *)(t + 1))[i];
+
+   if (i)
+   BTF_PRINT_ARG(", ");
+   BTF_PRINT_TYPE(arg_type);
+   }
+   BTF_PRINT_ARG(")");
+   

[PATCH bpf-next v3 06/13] tools/bpf: sync kernel uapi bpf.h header to tools directory

2018-10-17 Thread Yonghong Song
The kernel uapi bpf.h is synced to tools directory.

Signed-off-by: Yonghong Song 
---
 tools/include/uapi/linux/bpf.h | 11 +++
 1 file changed, 11 insertions(+)

diff --git a/tools/include/uapi/linux/bpf.h b/tools/include/uapi/linux/bpf.h
index f9187b41dff6..7ebbf4f06a65 100644
--- a/tools/include/uapi/linux/bpf.h
+++ b/tools/include/uapi/linux/bpf.h
@@ -332,6 +332,9 @@ union bpf_attr {
 * (context accesses, allowed helpers, etc).
 */
__u32   expected_attach_type;
+   __u32   prog_btf_fd;/* fd pointing to BTF type data 
*/
+   __u32   func_info_len;  /* func_info length */
+   __aligned_u64   func_info;  /* func type info */
};
 
struct { /* anonymous struct used by BPF_OBJ_* commands */
@@ -2585,6 +2588,9 @@ struct bpf_prog_info {
__u32 nr_jited_func_lens;
__aligned_u64 jited_ksyms;
__aligned_u64 jited_func_lens;
+   __u32 btf_id;
+   __u32 nr_jited_func_types;
+   __aligned_u64 jited_func_types;
 } __attribute__((aligned(8)));
 
 struct bpf_map_info {
@@ -2896,4 +2902,9 @@ struct bpf_flow_keys {
};
 };
 
+struct bpf_func_info {
+   __u32   insn_offset;
+   __u32   type_id;
+};
+
 #endif /* _UAPI__LINUX_BPF_H__ */
-- 
2.17.1



[PATCH bpf-next v3 10/13] tools/bpf: do not use pahole if clang/llvm can generate BTF sections

2018-10-17 Thread Yonghong Song
Add additional checks in tools/testing/selftests/bpf and
samples/bpf such that if clang/llvm compiler can generate
BTF sections, do not use pahole.

Signed-off-by: Yonghong Song 
---
 samples/bpf/Makefile | 8 
 tools/testing/selftests/bpf/Makefile | 8 
 2 files changed, 16 insertions(+)

diff --git a/samples/bpf/Makefile b/samples/bpf/Makefile
index be0a961450bc..870fe7ee2b69 100644
--- a/samples/bpf/Makefile
+++ b/samples/bpf/Makefile
@@ -208,12 +208,20 @@ endif
 BTF_LLC_PROBE := $(shell $(LLC) -march=bpf -mattr=help 2>&1 | grep dwarfris)
 BTF_PAHOLE_PROBE := $(shell $(BTF_PAHOLE) --help 2>&1 | grep BTF)
 BTF_OBJCOPY_PROBE := $(shell $(LLVM_OBJCOPY) --help 2>&1 | grep -i 
'usage.*llvm')
+BTF_LLVM_PROBE := $(shell echo "int main() { return 0; }" | \
+ clang -target bpf -O2 -g -c -x c - -o 
./llvm_btf_verify.o; \
+ readelf -S ./llvm_btf_verify.o | grep BTF; \
+ /bin/rm -f ./llvm_btf_verify.o)
 
+ifneq ($(BTF_LLVM_PROBE),)
+   EXTRA_CFLAGS += -g
+else
 ifneq ($(and $(BTF_LLC_PROBE),$(BTF_PAHOLE_PROBE),$(BTF_OBJCOPY_PROBE)),)
EXTRA_CFLAGS += -g
LLC_FLAGS += -mattr=dwarfris
DWARF2BTF = y
 endif
+endif
 
 # Trick to allow make to be run from this directory
 all:
diff --git a/tools/testing/selftests/bpf/Makefile 
b/tools/testing/selftests/bpf/Makefile
index d99dd6fc3fbe..8d5612724db8 100644
--- a/tools/testing/selftests/bpf/Makefile
+++ b/tools/testing/selftests/bpf/Makefile
@@ -121,7 +121,14 @@ $(OUTPUT)/test_xdp_noinline.o: CLANG_FLAGS += -fno-inline
 BTF_LLC_PROBE := $(shell $(LLC) -march=bpf -mattr=help 2>&1 | grep dwarfris)
 BTF_PAHOLE_PROBE := $(shell $(BTF_PAHOLE) --help 2>&1 | grep BTF)
 BTF_OBJCOPY_PROBE := $(shell $(LLVM_OBJCOPY) --help 2>&1 | grep -i 
'usage.*llvm')
+BTF_LLVM_PROBE := $(shell echo "int main() { return 0; }" | \
+ clang -target bpf -O2 -g -c -x c - -o 
./llvm_btf_verify.o; \
+ readelf -S ./llvm_btf_verify.o | grep BTF; \
+ /bin/rm -f ./llvm_btf_verify.o)
 
+ifneq ($(BTF_LLVM_PROBE),)
+   CLANG_FLAGS += -g
+else
 ifneq ($(BTF_LLC_PROBE),)
 ifneq ($(BTF_PAHOLE_PROBE),)
 ifneq ($(BTF_OBJCOPY_PROBE),)
@@ -131,6 +138,7 @@ ifneq ($(BTF_OBJCOPY_PROBE),)
 endif
 endif
 endif
+endif
 
 $(OUTPUT)/%.o: %.c
$(CLANG) $(CLANG_FLAGS) \
-- 
2.17.1



[PATCH bpf-next v3 12/13] tools/bpf: enhance test_btf file testing to test func info

2018-10-17 Thread Yonghong Song
Change the bpf programs test_btf_haskv.c and test_btf_nokv.c to
have two sections, and enhance test_btf.c test_file feature
to test btf func_info returned by the kernel.

Signed-off-by: Yonghong Song 
---
 tools/testing/selftests/bpf/test_btf.c   | 87 ++--
 tools/testing/selftests/bpf/test_btf_haskv.c | 16 +++-
 tools/testing/selftests/bpf/test_btf_nokv.c  | 16 +++-
 3 files changed, 106 insertions(+), 13 deletions(-)

diff --git a/tools/testing/selftests/bpf/test_btf.c 
b/tools/testing/selftests/bpf/test_btf.c
index e03a8cea4bb7..38ca942eba28 100644
--- a/tools/testing/selftests/bpf/test_btf.c
+++ b/tools/testing/selftests/bpf/test_btf.c
@@ -2180,13 +2180,13 @@ static struct btf_file_test file_tests[] = {
 },
 };
 
-static int file_has_btf_elf(const char *fn)
+static int file_has_btf_elf(const char *fn, bool *has_btf_ext)
 {
Elf_Scn *scn = NULL;
GElf_Ehdr ehdr;
+   int ret = 0;
int elf_fd;
Elf *elf;
-   int ret;
 
if (CHECK(elf_version(EV_CURRENT) == EV_NONE,
  "elf_version(EV_CURRENT) == EV_NONE"))
@@ -2218,14 +2218,12 @@ static int file_has_btf_elf(const char *fn)
}
 
sh_name = elf_strptr(elf, ehdr.e_shstrndx, sh.sh_name);
-   if (!strcmp(sh_name, BTF_ELF_SEC)) {
+   if (!strcmp(sh_name, BTF_ELF_SEC))
ret = 1;
-   goto done;
-   }
+   if (!strcmp(sh_name, BTF_EXT_ELF_SEC))
+   *has_btf_ext = true;
}
 
-   ret = 0;
-
 done:
close(elf_fd);
elf_end(elf);
@@ -2235,15 +2233,22 @@ static int file_has_btf_elf(const char *fn)
 static int do_test_file(unsigned int test_num)
 {
const struct btf_file_test *test = _tests[test_num - 1];
+   const char *expected_fnames[] = {"_dummy_tracepoint",
+"test_long_fname_1",
+"test_long_fname_2"};
+   __u32 func_lens[10], func_types[10], info_len;
+   struct bpf_prog_info info = {};
struct bpf_object *obj = NULL;
struct bpf_program *prog;
+   bool has_btf_ext = false;
+   struct btf *btf = NULL;
struct bpf_map *map;
-   int err;
+   int i, err, prog_fd;
 
fprintf(stderr, "BTF libbpf test[%u] (%s): ", test_num,
test->file);
 
-   err = file_has_btf_elf(test->file);
+   err = file_has_btf_elf(test->file, _btf_ext);
if (err == -1)
return err;
 
@@ -2271,6 +2276,7 @@ static int do_test_file(unsigned int test_num)
err = bpf_object__load(obj);
if (CHECK(err < 0, "bpf_object__load: %d", err))
goto done;
+   prog_fd = bpf_program__fd(prog);
 
map = bpf_object__find_map_by_name(obj, "btf_map");
if (CHECK(!map, "btf_map not found")) {
@@ -2285,6 +2291,69 @@ static int do_test_file(unsigned int test_num)
  test->btf_kv_notfound))
goto done;
 
+   if (!jit_enabled || !has_btf_ext)
+   goto skip_jit;
+
+   info_len = sizeof(struct bpf_prog_info);
+   info.nr_jited_func_types = ARRAY_SIZE(func_types);
+   info.nr_jited_func_lens = ARRAY_SIZE(func_lens);
+   info.jited_func_types = ptr_to_u64(_types[0]);
+   info.jited_func_lens = ptr_to_u64(_lens[0]);
+
+   err = bpf_obj_get_info_by_fd(prog_fd, , _len);
+
+   if (CHECK(err == -1, "invalid get info errno:%d", errno)) {
+   fprintf(stderr, "%s\n", btf_log_buf);
+   err = -1;
+   goto done;
+   }
+   if (CHECK(info.nr_jited_func_lens != 3,
+ "incorrect info.nr_jited_func_lens %d",
+ info.nr_jited_func_lens)) {
+   err = -1;
+   goto done;
+   }
+   if (CHECK(info.nr_jited_func_types != 3,
+ "incorrect info.nr_jited_func_types %d",
+ info.nr_jited_func_types)) {
+   err = -1;
+   goto done;
+   }
+   if (CHECK(info.btf_id == 0, "incorrect btf_id = 0")) {
+   err = -1;
+   goto done;
+   }
+
+   err = btf_get_from_id(info.btf_id, );
+   if (CHECK(err, "cannot get btf from kernel, err: %d", err))
+   goto done;
+
+   /* check three functions */
+   for (i = 0; i < 3; i++) {
+   const struct btf_type *t;
+   const char *fname;
+
+   t = btf__type_by_id(btf, func_types[i]);
+   if (CHECK(!t, "btf__type_by_id failure: id %u",
+ func_types[i])) {
+   err = -1;
+   goto done;
+   }
+
+   fname = btf__name_by_offset(btf, t->name_off);
+  

[PATCH bpf-next v3 05/13] bpf: get better bpf_prog ksyms based on btf func type_id

2018-10-17 Thread Yonghong Song
This patch added interface to load a program with the following
additional information:
   . prog_btf_fd
   . func_info and func_info_len
where func_info will provides function range and type_id
corresponding to each function.

If verifier agrees with function range provided by the user,
the bpf_prog ksym for each function will use the func name
provided in the type_id, which is supposed to provide better
encoding as it is not limited by 16 bytes program name
limitation and this is better for bpf program which contains
multiple subprograms.

The bpf_prog_info interface is also extended to
return btf_id and jited_func_types, so user spaces can
print out the function prototype for each jited function.

Signed-off-by: Yonghong Song 
---
 include/linux/bpf.h  |  2 +
 include/linux/bpf_verifier.h |  1 +
 include/linux/btf.h  |  2 +
 include/uapi/linux/bpf.h | 11 +
 kernel/bpf/btf.c |  4 +-
 kernel/bpf/core.c| 13 ++
 kernel/bpf/syscall.c | 86 +++-
 kernel/bpf/verifier.c| 46 +++
 8 files changed, 162 insertions(+), 3 deletions(-)

diff --git a/include/linux/bpf.h b/include/linux/bpf.h
index e60fff48288b..a99e038ce9c4 100644
--- a/include/linux/bpf.h
+++ b/include/linux/bpf.h
@@ -308,6 +308,8 @@ struct bpf_prog_aux {
void *security;
 #endif
struct bpf_prog_offload *offload;
+   struct btf *btf;
+   u32 type_id; /* type id for this prog/func */
union {
struct work_struct work;
struct rcu_head rcu;
diff --git a/include/linux/bpf_verifier.h b/include/linux/bpf_verifier.h
index 9e8056ec20fa..e84782ec50ac 100644
--- a/include/linux/bpf_verifier.h
+++ b/include/linux/bpf_verifier.h
@@ -201,6 +201,7 @@ static inline bool bpf_verifier_log_needed(const struct 
bpf_verifier_log *log)
 struct bpf_subprog_info {
u32 start; /* insn idx of function entry point */
u16 stack_depth; /* max. stack depth used by this function */
+   u32 type_id; /* btf type_id for this subprog */
 };
 
 /* single container for all structs
diff --git a/include/linux/btf.h b/include/linux/btf.h
index e076c4697049..7f2c0a4a45ea 100644
--- a/include/linux/btf.h
+++ b/include/linux/btf.h
@@ -46,5 +46,7 @@ void btf_type_seq_show(const struct btf *btf, u32 type_id, 
void *obj,
   struct seq_file *m);
 int btf_get_fd_by_id(u32 id);
 u32 btf_id(const struct btf *btf);
+const struct btf_type *btf_type_by_id(const struct btf *btf, u32 type_id);
+const char *btf_name_by_offset(const struct btf *btf, u32 offset);
 
 #endif
diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h
index f9187b41dff6..7ebbf4f06a65 100644
--- a/include/uapi/linux/bpf.h
+++ b/include/uapi/linux/bpf.h
@@ -332,6 +332,9 @@ union bpf_attr {
 * (context accesses, allowed helpers, etc).
 */
__u32   expected_attach_type;
+   __u32   prog_btf_fd;/* fd pointing to BTF type data 
*/
+   __u32   func_info_len;  /* func_info length */
+   __aligned_u64   func_info;  /* func type info */
};
 
struct { /* anonymous struct used by BPF_OBJ_* commands */
@@ -2585,6 +2588,9 @@ struct bpf_prog_info {
__u32 nr_jited_func_lens;
__aligned_u64 jited_ksyms;
__aligned_u64 jited_func_lens;
+   __u32 btf_id;
+   __u32 nr_jited_func_types;
+   __aligned_u64 jited_func_types;
 } __attribute__((aligned(8)));
 
 struct bpf_map_info {
@@ -2896,4 +2902,9 @@ struct bpf_flow_keys {
};
 };
 
+struct bpf_func_info {
+   __u32   insn_offset;
+   __u32   type_id;
+};
+
 #endif /* _UAPI__LINUX_BPF_H__ */
diff --git a/kernel/bpf/btf.c b/kernel/bpf/btf.c
index 763f8e06bc91..13e83f82374b 100644
--- a/kernel/bpf/btf.c
+++ b/kernel/bpf/btf.c
@@ -471,7 +471,7 @@ static bool btf_name_valid_identifier(const struct btf 
*btf, u32 offset)
return !*src;
 }
 
-static const char *btf_name_by_offset(const struct btf *btf, u32 offset)
+const char *btf_name_by_offset(const struct btf *btf, u32 offset)
 {
if (!offset)
return "(anon)";
@@ -481,7 +481,7 @@ static const char *btf_name_by_offset(const struct btf 
*btf, u32 offset)
return "(invalid-name-offset)";
 }
 
-static const struct btf_type *btf_type_by_id(const struct btf *btf, u32 
type_id)
+const struct btf_type *btf_type_by_id(const struct btf *btf, u32 type_id)
 {
if (type_id > btf->nr_types)
return NULL;
diff --git a/kernel/bpf/core.c b/kernel/bpf/core.c
index defcf4df6d91..4c4d414e030a 100644
--- a/kernel/bpf/core.c
+++ b/kernel/bpf/core.c
@@ -21,12 +21,14 @@
  * Kris Katterjohn - Added many additional checks in bpf_check_classic()
  */
 
+#include 
 #include 
 #include 
 #include 
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -387,6 +389,8 @

[PATCH bpf-next v3 09/13] tools/bpf: add support to read .BTF.ext sections

2018-10-17 Thread Yonghong Song
The .BTF section is already available to encode types.
These types can be used for map
pretty print. The whole .BTF will be passed to the
kernel as well for which kernel can verify and return
to the user space for pretty print etc.

The llvm patch at https://reviews.llvm.org/D53261
will generate .BTF section and one more section .BTF.ext.
The .BTF.ext section encodes function type
information and line information. Note that
this patch set only supports function type info.
The functionality is implemented in libbpf.

The .BTF section can be directly loaded into the
kernel, and the .BTF.ext section cannot. The loader
may need to do some relocation and merging,
similar to merging multiple code sections, before
loading into the kernel.

Signed-off-by: Yonghong Song 
---
 tools/lib/bpf/btf.c| 232 +
 tools/lib/bpf/btf.h|  48 +
 tools/lib/bpf/libbpf.c |  53 +-
 3 files changed, 329 insertions(+), 4 deletions(-)

diff --git a/tools/lib/bpf/btf.c b/tools/lib/bpf/btf.c
index 33095fc1860b..4748e0bacd2b 100644
--- a/tools/lib/bpf/btf.c
+++ b/tools/lib/bpf/btf.c
@@ -37,6 +37,11 @@ struct btf {
int fd;
 };
 
+struct btf_ext {
+   void *func_info;
+   __u32 func_info_len;
+};
+
 static int btf_add_type(struct btf *btf, struct btf_type *t)
 {
if (btf->types_size - btf->nr_types < 2) {
@@ -397,3 +402,230 @@ const char *btf__name_by_offset(const struct btf *btf, 
__u32 offset)
else
return NULL;
 }
+
+static int btf_ext_validate_func_info(const struct btf_sec_func_info *sinfo,
+ __u32 size, btf_print_fn_t err_log)
+{
+   int sec_hdrlen = sizeof(struct btf_sec_func_info);
+   __u32 record_size = sizeof(struct bpf_func_info);
+   __u32 size_left = size, num_records;
+   __u64 total_record_size;
+
+   while (size_left) {
+   if (size_left < sec_hdrlen) {
+   elog("BTF.ext func_info header not found");
+   return -EINVAL;
+   }
+
+   num_records = sinfo->num_func_info;
+   if (num_records == 0) {
+   elog("incorrect BTF.ext num_func_info");
+   return -EINVAL;
+   }
+
+   total_record_size = sec_hdrlen +
+   (__u64)num_records * record_size;
+   if (size_left < total_record_size) {
+   elog("incorrect BTF.ext num_func_info");
+   return -EINVAL;
+   }
+
+   size_left -= total_record_size;
+   sinfo = (void *)sinfo + total_record_size;
+   }
+
+   return 0;
+}
+static int btf_ext_parse_hdr(__u8 *data, __u32 data_size,
+btf_print_fn_t err_log)
+{
+   const struct btf_ext_header *hdr = (struct btf_ext_header *)data;
+   const struct btf_sec_func_info *sinfo;
+   __u32 meta_left, last_func_info_pos;
+
+   if (data_size < sizeof(*hdr)) {
+   elog("BTF.ext header not found");
+   return -EINVAL;
+   }
+
+   if (hdr->magic != BTF_MAGIC) {
+   elog("Invalid BTF.ext magic:%x\n", hdr->magic);
+   return -EINVAL;
+   }
+
+   if (hdr->version != BTF_VERSION) {
+   elog("Unsupported BTF.ext version:%u\n", hdr->version);
+   return -ENOTSUP;
+   }
+
+   if (hdr->flags) {
+   elog("Unsupported BTF.ext flags:%x\n", hdr->flags);
+   return -ENOTSUP;
+   }
+
+   meta_left = data_size - sizeof(*hdr);
+   if (!meta_left) {
+   elog("BTF.ext has no data\n");
+   return -EINVAL;
+   }
+
+   if (meta_left < hdr->func_info_off) {
+   elog("Invalid BTF.ext func_info section offset:%u\n",
+hdr->func_info_off);
+   return -EINVAL;
+   }
+
+   if (hdr->func_info_off & 0x02) {
+   elog("BTF.ext func_info section is not aligned to 4 bytes\n");
+   return -EINVAL;
+   }
+
+   last_func_info_pos = sizeof(*hdr) + hdr->func_info_off +
+hdr->func_info_len;
+   if (last_func_info_pos > data_size) {
+   elog("Invalid BTF.ext func_info section size:%u\n",
+hdr->func_info_len);
+   return -EINVAL;
+   }
+
+   sinfo = (const struct btf_sec_func_info *)(data + sizeof(*hdr) +
+  hdr->func_info_off);
+   return btf_ext_validate_func_info(sinfo, hdr->func_info_len,
+ err_log);
+}
+
+void btf_ext__free(struct btf_ext *btf_ext)
+{
+   if (!btf_ext)
+   return;
+
+   f

[PATCH bpf-next v3 01/13] bpf: btf: Break up btf_type_is_void()

2018-10-17 Thread Yonghong Song
This patch breaks up btf_type_is_void() into
btf_type_is_void() and btf_type_is_fwd().

It also adds btf_type_nosize() to better describe it is
testing a type has nosize info.

Signed-off-by: Martin KaFai Lau 
Signed-off-by: Yonghong Song 
---
 kernel/bpf/btf.c | 37 ++---
 1 file changed, 22 insertions(+), 15 deletions(-)

diff --git a/kernel/bpf/btf.c b/kernel/bpf/btf.c
index 378cef70341c..be406d8906ce 100644
--- a/kernel/bpf/btf.c
+++ b/kernel/bpf/btf.c
@@ -306,15 +306,22 @@ static bool btf_type_is_modifier(const struct btf_type *t)
 
 static bool btf_type_is_void(const struct btf_type *t)
 {
-   /* void => no type and size info.
-* Hence, FWD is also treated as void.
-*/
-   return t == _void || BTF_INFO_KIND(t->info) == BTF_KIND_FWD;
+   return t == _void;
+}
+
+static bool btf_type_is_fwd(const struct btf_type *t)
+{
+   return BTF_INFO_KIND(t->info) == BTF_KIND_FWD;
+}
+
+static bool btf_type_nosize(const struct btf_type *t)
+{
+   return btf_type_is_void(t) || btf_type_is_fwd(t);
 }
 
-static bool btf_type_is_void_or_null(const struct btf_type *t)
+static bool btf_type_nosize_or_null(const struct btf_type *t)
 {
-   return !t || btf_type_is_void(t);
+   return !t || btf_type_nosize(t);
 }
 
 /* union is only a special case of struct:
@@ -826,7 +833,7 @@ const struct btf_type *btf_type_id_size(const struct btf 
*btf,
u32 size = 0;
 
size_type = btf_type_by_id(btf, size_type_id);
-   if (btf_type_is_void_or_null(size_type))
+   if (btf_type_nosize_or_null(size_type))
return NULL;
 
if (btf_type_has_size(size_type)) {
@@ -842,7 +849,7 @@ const struct btf_type *btf_type_id_size(const struct btf 
*btf,
size = btf->resolved_sizes[size_type_id];
size_type_id = btf->resolved_ids[size_type_id];
size_type = btf_type_by_id(btf, size_type_id);
-   if (btf_type_is_void(size_type))
+   if (btf_type_nosize_or_null(size_type))
return NULL;
}
 
@@ -1164,7 +1171,7 @@ static int btf_modifier_resolve(struct btf_verifier_env 
*env,
}
 
/* "typedef void new_void", "const void"...etc */
-   if (btf_type_is_void(next_type))
+   if (btf_type_is_void(next_type) || btf_type_is_fwd(next_type))
goto resolved;
 
if (!env_type_is_resolve_sink(env, next_type) &&
@@ -1178,7 +1185,7 @@ static int btf_modifier_resolve(struct btf_verifier_env 
*env,
 * pretty print).
 */
if (!btf_type_id_size(btf, _type_id, _type_size) &&
-   !btf_type_is_void(btf_type_id_resolve(btf, _type_id))) {
+   !btf_type_nosize(btf_type_id_resolve(btf, _type_id))) {
btf_verifier_log_type(env, v->t, "Invalid type_id");
return -EINVAL;
}
@@ -1205,7 +1212,7 @@ static int btf_ptr_resolve(struct btf_verifier_env *env,
}
 
/* "void *" */
-   if (btf_type_is_void(next_type))
+   if (btf_type_is_void(next_type) || btf_type_is_fwd(next_type))
goto resolved;
 
if (!env_type_is_resolve_sink(env, next_type) &&
@@ -1235,7 +1242,7 @@ static int btf_ptr_resolve(struct btf_verifier_env *env,
}
 
if (!btf_type_id_size(btf, _type_id, _type_size) &&
-   !btf_type_is_void(btf_type_id_resolve(btf, _type_id))) {
+   !btf_type_nosize(btf_type_id_resolve(btf, _type_id))) {
btf_verifier_log_type(env, v->t, "Invalid type_id");
return -EINVAL;
}
@@ -1396,7 +1403,7 @@ static int btf_array_resolve(struct btf_verifier_env *env,
/* Check array->index_type */
index_type_id = array->index_type;
index_type = btf_type_by_id(btf, index_type_id);
-   if (btf_type_is_void_or_null(index_type)) {
+   if (btf_type_nosize_or_null(index_type)) {
btf_verifier_log_type(env, v->t, "Invalid index");
return -EINVAL;
}
@@ -1415,7 +1422,7 @@ static int btf_array_resolve(struct btf_verifier_env *env,
/* Check array->type */
elem_type_id = array->type;
elem_type = btf_type_by_id(btf, elem_type_id);
-   if (btf_type_is_void_or_null(elem_type)) {
+   if (btf_type_nosize_or_null(elem_type)) {
btf_verifier_log_type(env, v->t,
  "Invalid elem");
return -EINVAL;
@@ -1615,7 +1622,7 @@ static int btf_struct_resolve(struct btf_verifier_env 
*env,
const struct btf_type *member_type = btf_type_by_id(env->btf,
member_type_id);
 
-   if (btf_type_is_void_or_null(member_type)) {
+   if (btf_type_nosize_or_null(me

[PATCH bpf-next v3 08/13] tools/bpf: extends test_btf to test load/retrieve func_type info

2018-10-17 Thread Yonghong Song
A two function bpf program is loaded with btf and func_info.
After successful prog load, the bpf_get_info syscall is called
to retrieve prog info to ensure the types returned from the
kernel matches the types passed to the kernel from the
user space.

Several negative tests are also added to test loading/retriving
of func_type info.

Signed-off-by: Yonghong Song 
---
 tools/testing/selftests/bpf/test_btf.c | 278 -
 1 file changed, 275 insertions(+), 3 deletions(-)

diff --git a/tools/testing/selftests/bpf/test_btf.c 
b/tools/testing/selftests/bpf/test_btf.c
index b6461c3c5e11..e03a8cea4bb7 100644
--- a/tools/testing/selftests/bpf/test_btf.c
+++ b/tools/testing/selftests/bpf/test_btf.c
@@ -5,6 +5,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -22,9 +23,13 @@
 #include "bpf_rlimit.h"
 #include "bpf_util.h"
 
+#define MAX_INSNS  512
+#define MAX_SUBPROGS   16
+
 static uint32_t pass_cnt;
 static uint32_t error_cnt;
 static uint32_t skip_cnt;
+static bool jit_enabled;
 
 #define CHECK(condition, format...) ({ \
int __ret = !!(condition);  \
@@ -60,6 +65,24 @@ static int __base_pr(const char *format, ...)
return err;
 }
 
+static bool is_jit_enabled(void)
+{
+   const char *jit_sysctl = "/proc/sys/net/core/bpf_jit_enable";
+   bool enabled = false;
+   int sysctl_fd;
+
+   sysctl_fd = open(jit_sysctl, 0, O_RDONLY);
+   if (sysctl_fd != -1) {
+   char tmpc;
+
+   if (read(sysctl_fd, , sizeof(tmpc)) == 1)
+   enabled = (tmpc != '0');
+   close(sysctl_fd);
+   }
+
+   return enabled;
+}
+
 #define BTF_INFO_ENC(kind, root, vlen) \
((!!(root) << 31) | ((kind) << 24) | ((vlen) & BTF_MAX_VLEN))
 
@@ -103,6 +126,7 @@ static struct args {
bool get_info_test;
bool pprint_test;
bool always_log;
+   bool func_type_test;
 } args;
 
 static char btf_log_buf[BTF_LOG_BUF_SIZE];
@@ -2693,16 +2717,256 @@ static int test_pprint(void)
return err;
 }
 
+static struct btf_func_type_test {
+   const char *descr;
+   const char *str_sec;
+   __u32 raw_types[MAX_NR_RAW_TYPES];
+   __u32 str_sec_size;
+   struct bpf_insn insns[MAX_INSNS];
+   __u32 prog_type;
+   struct bpf_func_info func_info[MAX_SUBPROGS];
+   __u32 func_info_len;
+   bool expected_prog_load_failure;
+} func_type_test[] = {
+
+{
+   .descr = "func_type test #1",
+   .str_sec = "\0int\0unsigned int\0funcA\0funcB",
+   .raw_types = {
+   BTF_TYPE_INT_ENC(NAME_TBD, BTF_INT_SIGNED, 0, 32, 4),  /* [1] */
+   BTF_TYPE_INT_ENC(NAME_TBD, 0, 0, 32, 4),   /* [2] */
+   BTF_TYPE_ENC(NAME_TBD, BTF_INFO_ENC(BTF_KIND_FUNC, 0, 2), 1),  
/* [3] */
+   1, 2,
+   BTF_TYPE_ENC(NAME_TBD, BTF_INFO_ENC(BTF_KIND_FUNC, 0, 2), 1),  
/* [4] */
+   2, 1,
+   BTF_END_RAW,
+   },
+   .str_sec_size = sizeof("\0int\0unsigned int\0funcA\0funcB"),
+   .insns = {
+   BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 1, 0, 2),
+   BPF_MOV64_IMM(BPF_REG_0, 1),
+   BPF_EXIT_INSN(),
+   BPF_MOV64_IMM(BPF_REG_0, 2),
+   BPF_EXIT_INSN(),
+   },
+   .prog_type = BPF_PROG_TYPE_TRACEPOINT,
+   .func_info = { {0, 3}, {3, 4} },
+   .func_info_len = 2 * sizeof(struct bpf_func_info),
+},
+
+{
+   .descr = "func_type test #2",
+   .str_sec = "\0int\0unsigned int\0funcA\0funcB",
+   .raw_types = {
+   BTF_TYPE_INT_ENC(NAME_TBD, BTF_INT_SIGNED, 0, 32, 4),  /* [1] */
+   BTF_TYPE_INT_ENC(NAME_TBD, 0, 0, 32, 4),   /* [2] */
+   /* incorrect func type */
+   BTF_TYPE_ENC(NAME_TBD, BTF_INFO_ENC(BTF_KIND_FUNC_PROTO, 0, 2), 
1),  /* [3] */
+   1, 2,
+   BTF_TYPE_ENC(NAME_TBD, BTF_INFO_ENC(BTF_KIND_FUNC, 0, 2), 1),  
/* [4] */
+   2, 1,
+   BTF_END_RAW,
+   },
+   .str_sec_size = sizeof("\0int\0unsigned int\0funcA\0funcB"),
+   .insns = {
+   BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 1, 0, 2),
+   BPF_MOV64_IMM(BPF_REG_0, 1),
+   BPF_EXIT_INSN(),
+   BPF_MOV64_IMM(BPF_REG_0, 2),
+   BPF_EXIT_INSN(),
+   },
+   .prog_type = BPF_PROG_TYPE_TRACEPOINT,
+   .func_info = { {0, 3}, {3, 4} },
+   .func_info_len = 2 * sizeof(struct bpf_func_info),
+   .expected_prog_load_failure = true,
+},
+
+{
+   .descr = "func_type test #3",
+   .str_sec = "\0int\0unsigned int\0funcA\0funcB",
+   .raw_types = {
+   BTF_TYPE_INT_ENC(NAME_TBD, BTF_INT_SIGNED, 0, 32, 4),  /* [1] */
+ 

[PATCH bpf-next v3 04/13] tools/bpf: add btf func/func_proto unit tests in selftest test_btf

2018-10-17 Thread Yonghong Song
Add several BTF_KIND_FUNC and BTF_KIND_FUNC_PROTO
unit tests in bpf selftest test_btf.

Signed-off-by: Martin KaFai Lau 
Signed-off-by: Yonghong Song 
---
 tools/lib/bpf/btf.c|   4 +
 tools/testing/selftests/bpf/test_btf.c | 216 +
 2 files changed, 220 insertions(+)

diff --git a/tools/lib/bpf/btf.c b/tools/lib/bpf/btf.c
index 449591aa9900..33095fc1860b 100644
--- a/tools/lib/bpf/btf.c
+++ b/tools/lib/bpf/btf.c
@@ -165,6 +165,10 @@ static int btf_parse_type_sec(struct btf *btf, 
btf_print_fn_t err_log)
case BTF_KIND_ENUM:
next_type += vlen * sizeof(struct btf_enum);
break;
+   case BTF_KIND_FUNC:
+   case BTF_KIND_FUNC_PROTO:
+   next_type += vlen * sizeof(int);
+   break;
case BTF_KIND_TYPEDEF:
case BTF_KIND_PTR:
case BTF_KIND_FWD:
diff --git a/tools/testing/selftests/bpf/test_btf.c 
b/tools/testing/selftests/bpf/test_btf.c
index f42b3396d622..b6461c3c5e11 100644
--- a/tools/testing/selftests/bpf/test_btf.c
+++ b/tools/testing/selftests/bpf/test_btf.c
@@ -1374,6 +1374,222 @@ static struct btf_raw_test raw_tests[] = {
.map_create_err = true,
 },
 
+{
+   .descr = "func pointer #1",
+   .raw_types = {
+   BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4),  /* [1] */
+   BTF_TYPE_INT_ENC(0, 0, 0, 32, 4),   /* [2] */
+   /* int (*func)(int, unsigned int) */
+   BTF_TYPE_ENC(0, BTF_INFO_ENC(BTF_KIND_FUNC_PROTO, 0, 2), 1),
/* [3] */
+   1, 2,
+   BTF_TYPE_ENC(0, BTF_INFO_ENC(BTF_KIND_PTR, 0, 0), 3),   /* [4] 
*/
+   BTF_END_RAW,
+   },
+   .str_sec = "",
+   .str_sec_size = sizeof(""),
+   .map_type = BPF_MAP_TYPE_ARRAY,
+   .map_name = "func_type_check_btf",
+   .key_size = sizeof(int),
+   .value_size = sizeof(int),
+   .key_type_id = 1,
+   .value_type_id = 1,
+   .max_entries = 4,
+},
+
+{
+   .descr = "func pointer #2",
+   .raw_types = {
+   BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4),  /* [1] */
+   BTF_TYPE_INT_ENC(0, 0, 0, 32, 4),   /* [2] */
+   /* void (*func)(int, unsigned int, ) */
+   BTF_TYPE_ENC(0, BTF_INFO_ENC(BTF_KIND_FUNC_PROTO, 0, 3), 0),
/* [3] */
+   1, 2, 0,
+   BTF_TYPE_ENC(0, BTF_INFO_ENC(BTF_KIND_PTR, 0, 0), 3),   /* [4] 
*/
+   BTF_END_RAW,
+   },
+   .str_sec = "",
+   .str_sec_size = sizeof(""),
+   .map_type = BPF_MAP_TYPE_ARRAY,
+   .map_name = "func_type_check_btf",
+   .key_size = sizeof(int),
+   .value_size = sizeof(int),
+   .key_type_id = 1,
+   .value_type_id = 1,
+   .max_entries = 4,
+},
+
+{
+   .descr = "func pointer #3",
+   .raw_types = {
+   BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4),  /* [1] */
+   BTF_TYPE_INT_ENC(0, 0, 0, 32, 4),   /* [2] */
+   /* void (*func)(void, int, unsigned int) */
+   BTF_TYPE_ENC(0, BTF_INFO_ENC(BTF_KIND_FUNC_PROTO, 0, 3), 0),
/* [3] */
+   1, 0, 2,
+   BTF_TYPE_ENC(0, BTF_INFO_ENC(BTF_KIND_PTR, 0, 0), 3),   /* [4] 
*/
+   BTF_END_RAW,
+   },
+   .str_sec = "",
+   .str_sec_size = sizeof(""),
+   .map_type = BPF_MAP_TYPE_ARRAY,
+   .map_name = "func_type_check_btf",
+   .key_size = sizeof(int),
+   .value_size = sizeof(int),
+   .key_type_id = 1,
+   .value_type_id = 1,
+   .max_entries = 4,
+   .btf_load_err = true,
+   .err_str = "Invalid arg#2",
+},
+
+{
+   .descr = "func pointer #4",
+   .raw_types = {
+   BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4),  /* [1] */
+   BTF_TYPE_INT_ENC(0, 0, 0, 32, 4),   /* [2] */
+   /*
+* Testing:
+* BTF_KIND_CONST => BTF_KIND_TYPEDEF => BTF_KIND_PTR =>
+* BTF_KIND_FUNC_PROTO
+*/
+   /* typedef void (*func_ptr)(int, unsigned int) */
+   BTF_TYPE_ENC(0, BTF_INFO_ENC(BTF_KIND_TYPEDEF, 0, 0), 5),/* [3] 
*/
+   /* const func_ptr */
+   BTF_TYPE_ENC(0, BTF_INFO_ENC(BTF_KIND_CONST, 0, 0), 3), /* [4] 
*/
+   BTF_TYPE_ENC(0, BTF_INFO_ENC(BTF_KIND_PTR, 0, 0), 6),   /* [5] 
*/
+   BTF_TYPE_ENC(0, BTF_INFO_ENC(BTF_KIND_FUNC_PROTO, 0, 2), 0),
/* [6] */
+   1, 2,
+   BTF_END_RAW,
+   },
+   .str_sec = "",
+   .str_sec_size = sizeof(""),
+   .map_type = BPF_MAP_TYPE_ARRAY,
+   .map_name = "func_type_check_btf",
+   .ke

[PATCH bpf-next v3 02/13] bpf: btf: Add BTF_KIND_FUNC and BTF_KIND_FUNC_PROTO

2018-10-17 Thread Yonghong Song
This patch adds BTF_KIND_FUNC and BTF_KIND_FUNC_PROTO
support to the type section. BTF_KIND_FUNC_PROTO is used
to specify the type of a function pointer. With this,
BTF has a complete set of C types (except float).

BTF_KIND_FUNC is used to specify the signature of a
defined subprogram. BTF_KIND_FUNC_PROTO can be referenced
by another type, e.g., a pointer type, and BTF_KIND_FUNC
type cannot be referenced by another type.

For both BTF_KIND_FUNC and BTF_KIND_FUNC_PROTO types,
the func return type is in t->type (where t is a
"struct btf_type" object). The func args are an array of
u32s immediately following object "t".

As a concrete example, for the C program below,
  $ cat test.c
  int foo(int (*bar)(int)) { return bar(5); }
with LLVM patch https://reviews.llvm.org/D53261
in Debug mode, we have
  $ clang -target bpf -g -O2 -mllvm -debug-only=btf -c test.c
  Type Table:
  [1] FUNC NameOff=1 Info=0x0c01 Size/Type=2
  ParamType=3
  [2] INT NameOff=11 Info=0x0100 Size/Type=4
  Desc=0x0120
  [3] PTR NameOff=0 Info=0x0200 Size/Type=4
  [4] FUNC_PROTO NameOff=0 Info=0x0d01 Size/Type=2
  ParamType=2

  String Table:
  0 :
  1 : foo
  5 : .text
  11 : int
  15 : test.c
  22 : int foo(int (*bar)(int)) { return bar(5); }

  FuncInfo Table:
  SecNameOff=5
  InsnOffset= TypeId=1

  ...

(Eventually we shall have bpftool to dump btf information
 like the above.)

Function "foo" has a FUNC type (type_id = 1).
The parameter of "foo" has type_id 3 which is PTR->FUNC_PROTO,
where FUNC_PROTO refers to function pointer "bar".

In FuncInfo Table, for section .text, the function,
with to-be-determined offset (marked as ),
has type_id=1 which refers to a FUNC type.
This way, the function signature is
available to both kernel and user space.
Here, the insn offset is not available during the dump time
as relocation is resolved pretty late in the compilation process.

Signed-off-by: Martin KaFai Lau 
Signed-off-by: Yonghong Song 
---
 include/uapi/linux/btf.h |   9 +-
 kernel/bpf/btf.c | 280 ++-
 2 files changed, 253 insertions(+), 36 deletions(-)

diff --git a/include/uapi/linux/btf.h b/include/uapi/linux/btf.h
index 972265f32871..63f8500e6f34 100644
--- a/include/uapi/linux/btf.h
+++ b/include/uapi/linux/btf.h
@@ -40,7 +40,8 @@ struct btf_type {
/* "size" is used by INT, ENUM, STRUCT and UNION.
 * "size" tells the size of the type it is describing.
 *
-* "type" is used by PTR, TYPEDEF, VOLATILE, CONST and RESTRICT.
+* "type" is used by PTR, TYPEDEF, VOLATILE, CONST, RESTRICT,
+* FUNC and FUNC_PROTO.
 * "type" is a type_id referring to another type.
 */
union {
@@ -64,8 +65,10 @@ struct btf_type {
 #define BTF_KIND_VOLATILE  9   /* Volatile */
 #define BTF_KIND_CONST 10  /* Const*/
 #define BTF_KIND_RESTRICT  11  /* Restrict */
-#define BTF_KIND_MAX   11
-#define NR_BTF_KINDS   12
+#define BTF_KIND_FUNC  12  /* Function */
+#define BTF_KIND_FUNC_PROTO13  /* Function Prototype   */
+#define BTF_KIND_MAX   13
+#define NR_BTF_KINDS   14
 
 /* For some specific BTF_KIND, "struct btf_type" is immediately
  * followed by extra data.
diff --git a/kernel/bpf/btf.c b/kernel/bpf/btf.c
index be406d8906ce..763f8e06bc91 100644
--- a/kernel/bpf/btf.c
+++ b/kernel/bpf/btf.c
@@ -5,6 +5,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -259,6 +260,8 @@ static const char * const btf_kind_str[NR_BTF_KINDS] = {
[BTF_KIND_VOLATILE] = "VOLATILE",
[BTF_KIND_CONST]= "CONST",
[BTF_KIND_RESTRICT] = "RESTRICT",
+   [BTF_KIND_FUNC] = "FUNC",
+   [BTF_KIND_FUNC_PROTO]   = "FUNC_PROTO",
 };
 
 struct btf_kind_operations {
@@ -281,6 +284,9 @@ struct btf_kind_operations {
 static const struct btf_kind_operations * const kind_ops[NR_BTF_KINDS];
 static struct btf_type btf_void;
 
+static int btf_resolve(struct btf_verifier_env *env,
+  const struct btf_type *t, u32 type_id);
+
 static bool btf_type_is_modifier(const struct btf_type *t)
 {
/* Some of them is not strictly a C modifier
@@ -314,9 +320,20 @@ static bool btf_type_is_fwd(const struct btf_type *t)
return BTF_INFO_KIND(t->info) == BTF_KIND_FWD;
 }
 
+static bool btf_type_is_func(const struct btf_type *t)
+{
+   return BTF_INFO_KIND(t->info) == BTF_KIND_FUNC;
+}
+
+static bool btf_type_is_func_proto(const struct btf_type *t)
+{
+   return BTF_INFO_KIND(t->info) == BTF_KIND_FUNC_PROTO;
+}
+
 static bool btf_type_nosize(const struct btf_type *t)
 {
-   return btf_type_is_void(t) || btf_type_is_fwd(t);
+   return btf_type_is_

[PATCH bpf-next v3 00/13] bpf: add btf func info support

2018-10-17 Thread Yonghong Song
The BTF support was added to kernel by Commit 69b693f0aefa
("bpf: btf: Introduce BPF Type Format (BTF)"), which introduced
.BTF section into ELF file and is primarily
used for map pretty print.
pahole is used to convert dwarf to BTF for ELF files.

This patch added func info support to the kernel so we can
get better ksym's for bpf function calls. Basically,
pairs of bpf function calls and their corresponding types
are passed to the kernel. Extracting function names from
the types, the kernel is able to construct a ksym for
each function call with embedded function name.

This patch set added support of FUNC and FUNC_PROTO types
in the kernel. LLVM patch https://reviews.llvm.org/D53261
can generate func info, encoded in .BTF.ext ELF section.
The following is an example to show FUNC and
FUNC_PROTO difference, compiled with the above LLVM patch
with Debug mode.

  -bash-4.2$ cat test.c
  int foo(int (*bar)(int)) { return bar(5); }
  -bash-4.2$ clang -target bpf -g -O2 -mllvm -debug-only=btf -c test.c
  Type Table:
  [1] FUNC name_off=1 info=0x0c01 size/type=2
param_type=3
  [2] INT name_off=11 info=0x0100 size/type=4
desc=0x0120
  [3] PTR name_off=0 info=0x0200 size/type=4
  [4] FUNC_PROTO name_off=0 info=0x0d01 size/type=2
param_type=2

  String Table:
  0 :
  1 : foo
  5 : .text
  11 : int
  15 : test.c
  22 : int foo(int (*bar)(int)) { return bar(5); }

  FuncInfo Table:
  sec_name_off=5
insn_offset= type_id=1
  ...
  
In the above, type and string tables are in .BTF section and
the func info in .BTF.ext. The "" is the
insn offset which is not available during the dump time but
resolved during later compilation process.
Following the format specification at Patch #9 and examine the
raw data in .BTF.ext section, we have
  FuncInfo Table:
  sec_name_off=5
insn_offset=0 type_id=1
The (insn_offset, type_id) can be passed to the kernel
so the kernel can find the func name and use it in the ksym.
Below is a demonstration from Patch #13.
  $ bpftool prog dump jited id 1
  int _dummy_tracepoint(struct dummy_tracepoint_args * ):
  bpf_prog_b07ccb89267cf242__dummy_tracepoint:
 0:   push   %rbp
 1:   mov%rsp,%rbp
..
3c:   add$0x28,%rbp
40:   leaveq
41:   retq
  
  int test_long_fname_1(struct dummy_tracepoint_args * ):
  bpf_prog_2dcecc18072623fc_test_long_fname_1:
 0:   push   %rbp
 1:   mov%rsp,%rbp
..
3a:   add$0x28,%rbp
3e:   leaveq
3f:   retq
  
  int test_long_fname_2(struct dummy_tracepoint_args * ):
  bpf_prog_89d64e4abf0f0126_test_long_fname_2:
 0:   push   %rbp
 1:   mov%rsp,%rbp
..
80:   add$0x28,%rbp
84:   leaveq
85:   retq

For the patchset,
Patch #1  refactors the code to break up btf_type_is_void().
Patch #2  introduces new BTF types BTF_KIND_FUNC and BTF_KIND_FUNC_PROTO.
Patch #3  syncs btf.h header to tools directory.
Patch #4  adds btf func/func_proto self tests in test_btf.
Patch #5  adds kernel interface to load func_info to kernel
  and pass func_info to userspace.
Patch #6  syncs bpf.h header to tools directory.
Patch #7  adds news btf/func_info related fields in libbpf
  program load function.
Patch #8  extends selftest test_btf to test load/retrieve func_type info.
Patch #9  adds .BTF.ext func info support.
Patch #10 changes Makefile to avoid using pahole if llvm is capable of
  generating BTF sections.
Patch #11 refactors to have btf_get_from_id() in libbpf for reuse.
Patch #12 enhance test_btf file testing to test func info.
Patch #13 adds bpftool support for func signature dump.

Changelogs:
  v2 -> v3:
. Removed kernel btf extern functions btf_type_id_func()
  and btf_get_name_by_id(). Instead, exposing existing
  functions btf_type_by_id() and btf_name_by_offset().
. Added comments about ELF section .BTF.ext layout.
. Better codes in btftool as suggested by Edward Cree.
  v1 -> v2:
. Added missing sign-off.
. Limited the func_name/struct_member_name length for validity test.
. Removed/changed several verifier messages.
. Modified several commit messages to remove line_off reference.

Yonghong Song (13):
  bpf: btf: Break up btf_type_is_void()
  bpf: btf: Add BTF_KIND_FUNC and BTF_KIND_FUNC_PROTO
  tools/bpf: sync kernel btf.h header
  tools/bpf: add btf func/func_proto unit tests in selftest test_btf
  bpf: get better bpf_prog ksyms based on btf func type_id
  tools/bpf: sync kernel uapi bpf.h header to tools directory
  tools/bpf: add new fields for program load in lib/bpf
  tools/bpf: extends test_btf to test load/retrieve func_type info
  tools/bpf: add support to read .BTF.ext sections
  tools/bpf: do not use pahole if clang/llvm can generate BTF sections
  tools/bpf: refactor to implement btf_get_from_id() in lib/bpf
  tools/bpf: enhance test_btf file testing

[PATCH bpf-next v3 11/13] tools/bpf: refactor to implement btf_get_from_id() in lib/bpf

2018-10-17 Thread Yonghong Song
The function get_btf() is implemented in tools/bpf/bpftool/map.c
to get a btf structure given a map_info. This patch
refactored this function to be function btf_get_from_id()
in tools/lib/bpf so that it can be used later.

Signed-off-by: Yonghong Song 
---
 tools/bpf/bpftool/map.c | 68 ++--
 tools/lib/bpf/btf.c | 69 +
 tools/lib/bpf/btf.h | 18 ++-
 3 files changed, 81 insertions(+), 74 deletions(-)

diff --git a/tools/bpf/bpftool/map.c b/tools/bpf/bpftool/map.c
index 7bf38f0e152e..1b8a75fa0471 100644
--- a/tools/bpf/bpftool/map.c
+++ b/tools/bpf/bpftool/map.c
@@ -215,70 +215,6 @@ static int do_dump_btf(const struct btf_dumper *d,
return ret;
 }
 
-static int get_btf(struct bpf_map_info *map_info, struct btf **btf)
-{
-   struct bpf_btf_info btf_info = { 0 };
-   __u32 len = sizeof(btf_info);
-   __u32 last_size;
-   int btf_fd;
-   void *ptr;
-   int err;
-
-   err = 0;
-   *btf = NULL;
-   btf_fd = bpf_btf_get_fd_by_id(map_info->btf_id);
-   if (btf_fd < 0)
-   return 0;
-
-   /* we won't know btf_size until we call bpf_obj_get_info_by_fd(). so
-* let's start with a sane default - 4KiB here - and resize it only if
-* bpf_obj_get_info_by_fd() needs a bigger buffer.
-*/
-   btf_info.btf_size = 4096;
-   last_size = btf_info.btf_size;
-   ptr = malloc(last_size);
-   if (!ptr) {
-   err = -ENOMEM;
-   goto exit_free;
-   }
-
-   bzero(ptr, last_size);
-   btf_info.btf = ptr_to_u64(ptr);
-   err = bpf_obj_get_info_by_fd(btf_fd, _info, );
-
-   if (!err && btf_info.btf_size > last_size) {
-   void *temp_ptr;
-
-   last_size = btf_info.btf_size;
-   temp_ptr = realloc(ptr, last_size);
-   if (!temp_ptr) {
-   err = -ENOMEM;
-   goto exit_free;
-   }
-   ptr = temp_ptr;
-   bzero(ptr, last_size);
-   btf_info.btf = ptr_to_u64(ptr);
-   err = bpf_obj_get_info_by_fd(btf_fd, _info, );
-   }
-
-   if (err || btf_info.btf_size > last_size) {
-   err = errno;
-   goto exit_free;
-   }
-
-   *btf = btf__new((__u8 *)btf_info.btf, btf_info.btf_size, NULL);
-   if (IS_ERR(*btf)) {
-   err = PTR_ERR(*btf);
-   *btf = NULL;
-   }
-
-exit_free:
-   close(btf_fd);
-   free(ptr);
-
-   return err;
-}
-
 static json_writer_t *get_btf_writer(void)
 {
json_writer_t *jw = jsonw_new(stdout);
@@ -765,7 +701,7 @@ static int do_dump(int argc, char **argv)
 
prev_key = NULL;
 
-   err = get_btf(, );
+   err = btf_get_from_id(info.btf_id, );
if (err) {
p_err("failed to get btf");
goto exit_free;
@@ -909,7 +845,7 @@ static int do_lookup(int argc, char **argv)
}
 
/* here means bpf_map_lookup_elem() succeeded */
-   err = get_btf(, );
+   err = btf_get_from_id(info.btf_id, );
if (err) {
p_err("failed to get btf");
goto exit_free;
diff --git a/tools/lib/bpf/btf.c b/tools/lib/bpf/btf.c
index 4748e0bacd2b..ab654628e966 100644
--- a/tools/lib/bpf/btf.c
+++ b/tools/lib/bpf/btf.c
@@ -42,6 +42,11 @@ struct btf_ext {
__u32 func_info_len;
 };
 
+static inline __u64 ptr_to_u64(const void *ptr)
+{
+   return (__u64) (unsigned long) ptr;
+}
+
 static int btf_add_type(struct btf *btf, struct btf_type *t)
 {
if (btf->types_size - btf->nr_types < 2) {
@@ -403,6 +408,70 @@ const char *btf__name_by_offset(const struct btf *btf, 
__u32 offset)
return NULL;
 }
 
+int btf_get_from_id(__u32 id, struct btf **btf)
+{
+   struct bpf_btf_info btf_info = { 0 };
+   __u32 len = sizeof(btf_info);
+   __u32 last_size;
+   int btf_fd;
+   void *ptr;
+   int err;
+
+   err = 0;
+   *btf = NULL;
+   btf_fd = bpf_btf_get_fd_by_id(id);
+   if (btf_fd < 0)
+   return 0;
+
+   /* we won't know btf_size until we call bpf_obj_get_info_by_fd(). so
+* let's start with a sane default - 4KiB here - and resize it only if
+* bpf_obj_get_info_by_fd() needs a bigger buffer.
+*/
+   btf_info.btf_size = 4096;
+   last_size = btf_info.btf_size;
+   ptr = malloc(last_size);
+   if (!ptr) {
+   err = -ENOMEM;
+   goto exit_free;
+   }
+
+   bzero(ptr, last_size);
+   btf_info.btf = ptr_to_u64(ptr);
+   err = bpf_obj_get_info_by_fd(btf_fd, _info, );
+
+   if (!err && btf_info.btf_size > last_size) {
+   void *temp_ptr;
+
+   last_size = btf_info.btf_size;
+   temp_ptr = realloc(ptr, last_size);
+  

[PATCH bpf-next v3 03/13] tools/bpf: sync kernel btf.h header

2018-10-17 Thread Yonghong Song
The kernel uapi btf.h is synced to the tools directory.

Signed-off-by: Martin KaFai Lau 
Signed-off-by: Yonghong Song 
---
 tools/include/uapi/linux/btf.h | 9 ++---
 1 file changed, 6 insertions(+), 3 deletions(-)

diff --git a/tools/include/uapi/linux/btf.h b/tools/include/uapi/linux/btf.h
index 972265f32871..63f8500e6f34 100644
--- a/tools/include/uapi/linux/btf.h
+++ b/tools/include/uapi/linux/btf.h
@@ -40,7 +40,8 @@ struct btf_type {
/* "size" is used by INT, ENUM, STRUCT and UNION.
 * "size" tells the size of the type it is describing.
 *
-* "type" is used by PTR, TYPEDEF, VOLATILE, CONST and RESTRICT.
+* "type" is used by PTR, TYPEDEF, VOLATILE, CONST, RESTRICT,
+* FUNC and FUNC_PROTO.
 * "type" is a type_id referring to another type.
 */
union {
@@ -64,8 +65,10 @@ struct btf_type {
 #define BTF_KIND_VOLATILE  9   /* Volatile */
 #define BTF_KIND_CONST 10  /* Const*/
 #define BTF_KIND_RESTRICT  11  /* Restrict */
-#define BTF_KIND_MAX   11
-#define NR_BTF_KINDS   12
+#define BTF_KIND_FUNC  12  /* Function */
+#define BTF_KIND_FUNC_PROTO13  /* Function Prototype   */
+#define BTF_KIND_MAX   13
+#define NR_BTF_KINDS   14
 
 /* For some specific BTF_KIND, "struct btf_type" is immediately
  * followed by extra data.
-- 
2.17.1



[PATCH bpf-next v3 07/13] tools/bpf: add new fields for program load in lib/bpf

2018-10-17 Thread Yonghong Song
The new fields are added for program load in lib/bpf so
application uses api bpf_load_program_xattr() is able
to load program with btf and func_info data.

This functionality will be used in next patch
by bpf selftest test_btf.

Signed-off-by: Yonghong Song 
---
 tools/lib/bpf/bpf.c | 3 +++
 tools/lib/bpf/bpf.h | 3 +++
 2 files changed, 6 insertions(+)

diff --git a/tools/lib/bpf/bpf.c b/tools/lib/bpf/bpf.c
index d70a255cb05e..d8d48ab34220 100644
--- a/tools/lib/bpf/bpf.c
+++ b/tools/lib/bpf/bpf.c
@@ -196,6 +196,9 @@ int bpf_load_program_xattr(const struct 
bpf_load_program_attr *load_attr,
attr.log_level = 0;
attr.kern_version = load_attr->kern_version;
attr.prog_ifindex = load_attr->prog_ifindex;
+   attr.prog_btf_fd = load_attr->prog_btf_fd;
+   attr.func_info_len = load_attr->func_info_len;
+   attr.func_info = ptr_to_u64(load_attr->func_info);
memcpy(attr.prog_name, load_attr->name,
   min(name_len, BPF_OBJ_NAME_LEN - 1));
 
diff --git a/tools/lib/bpf/bpf.h b/tools/lib/bpf/bpf.h
index 258c3c178333..d2bdaffd7712 100644
--- a/tools/lib/bpf/bpf.h
+++ b/tools/lib/bpf/bpf.h
@@ -74,6 +74,9 @@ struct bpf_load_program_attr {
const char *license;
__u32 kern_version;
__u32 prog_ifindex;
+   __u32 prog_btf_fd;
+   __u32 func_info_len;
+   const struct bpf_func_info *func_info;
 };
 
 /* Flags to direct loading requirements */
-- 
2.17.1



Re: [PATCH bpf-next v2 13/13] tools/bpf: bpftool: add support for jited func types

2018-10-17 Thread Yonghong Song


On 10/17/18 4:11 AM, Edward Cree wrote:
> On 17/10/18 08:24, Yonghong Song wrote:
>> This patch added support to print function signature
>> if btf func_info is available. Note that ksym
>> now uses function name instead of prog_name as
>> prog_name has a limit of 16 bytes including
>> ending '\0'.
>>
>> The following is a sample output for selftests
>> test_btf with file test_btf_haskv.o:
>>
>>$ bpftool prog dump jited id 1
>>int _dummy_tracepoint(struct dummy_tracepoint_args * ):
>>bpf_prog_b07ccb89267cf242__dummy_tracepoint:
>>   0:   push   %rbp
>>   1:   mov%rsp,%rbp
>>  ..
>>  3c:   add$0x28,%rbp
>>  40:   leaveq
>>  41:   retq
>>
>>int test_long_fname_1(struct dummy_tracepoint_args * ):
>>bpf_prog_2dcecc18072623fc_test_long_fname_1:
>>   0:   push   %rbp
>>   1:   mov%rsp,%rbp
>>  ..
>>  3a:   add$0x28,%rbp
>>  3e:   leaveq
>>  3f:   retq
>>
>>int test_long_fname_2(struct dummy_tracepoint_args * ):
>>bpf_prog_89d64e4abf0f0126_test_long_fname_2:
>>   0:   push   %rbp
>>   1:   mov%rsp,%rbp
>>  ..
>>  80:   add$0x28,%rbp
>>  84:   leaveq
>>  85:   retq
>>
>> Signed-off-by: Yonghong Song 
>> ---
>>   tools/bpf/bpftool/btf_dumper.c | 96 ++
>>   tools/bpf/bpftool/main.h   |  2 +
>>   tools/bpf/bpftool/prog.c   | 54 +++
>>   3 files changed, 152 insertions(+)
>>
>> diff --git a/tools/bpf/bpftool/btf_dumper.c b/tools/bpf/bpftool/btf_dumper.c
>> index 55bc512a1831..a31df4202335 100644
>> --- a/tools/bpf/bpftool/btf_dumper.c
>> +++ b/tools/bpf/bpftool/btf_dumper.c
>> @@ -249,3 +249,99 @@ int btf_dumper_type(const struct btf_dumper *d, __u32 
>> type_id,
>>   {
>>  return btf_dumper_do_type(d, type_id, 0, data);
>>   }
>> +
>> +#define BTF_PRINT_STRING(str)   
>> \
>> +{   \
>> +pos += snprintf(func_sig + pos, size - pos, str);   \
>> +if (pos >= size)\
>> +return -1;  \
>> +}
> Usual kernel practice for this sort of macro is to use
>      do { \
>      } while(0)
>   to ensure correct behaviour if the macro is used within another control
>   flow statement, e.g.
>      if (x)
>      BTF_PRINT_STRING(x);
>      else
>      do_something_else();
>   will not compile with the bare braces as the else will be detached.

Thanks for the review! Will change to use the "do while" format
as you suggested.

>> +#define BTF_PRINT_ONE_ARG(fmt, arg) \
>> +{   \
>> +pos += snprintf(func_sig + pos, size - pos, fmt, arg);  \
>> +if (pos >= size)\
>> +return -1;  \
>> +}
> Any reason for not just using a variadic macro?

No particular reason. I will try to use it in the next revision.

>> +#define BTF_PRINT_TYPE_ONLY(type)   \
>> +{   \
>> +pos = __btf_dumper_type_only(btf, type, func_sig,   \
>> + pos, size);\
>> +if (pos == -1)  \
>> +return -1;  \
>> +}
>> +
>> +static int __btf_dumper_type_only(struct btf *btf, __u32 type_id,
>> +  char *func_sig, int pos, int size)
>> +{
>> +const struct btf_type *t = btf__type_by_id(btf, type_id);
>> +const struct btf_array *array;
>> +int i, vlen;
>> +
>> +switch (BTF_INFO_KIND(t->info)) {
>> +case BTF_KIND_INT:
>> +BTF_PRINT_ONE_ARG("%s ",
>> +  btf__name_by_offset(btf, t->name_off));
>> +break;
>> +case BTF_KIND_STRUCT:
>> +BTF_PRINT_ONE_ARG("struct %s ",
>> +  btf__name_by_offset(btf, t->name_off));
>> +break;
>> +case BTF_KIND_UNION:
>> +BTF_PRINT_ONE_ARG(&qu

Re: [PATCH bpf-next v2 02/13] bpf: btf: Add BTF_KIND_FUNC and BTF_KIND_FUNC_PROTO

2018-10-17 Thread Yonghong Song


On 10/17/18 9:13 AM, Edward Cree wrote:
> On 17/10/18 08:23, Yonghong Song wrote:
>> This patch adds BTF_KIND_FUNC and BTF_KIND_FUNC_PROTO
>> support to the type section. BTF_KIND_FUNC_PROTO is used
>> to specify the type of a function pointer. With this,
>> BTF has a complete set of C types (except float).
>>
>> BTF_KIND_FUNC is used to specify the signature of a
>> defined subprogram. BTF_KIND_FUNC_PROTO can be referenced
>> by another type, e.g., a pointer type, and BTF_KIND_FUNC
>> type cannot be referenced by another type.
> Why are distinct kinds created for these?  A function body is
>   a value of function type, and since there's no way (in C) to
>   declare a variable of function type (only pointer-to-
>   function), any declaration of function type must necessarily
>   be a BTF_KIND_FUNC, whereas any other reference to a function
>   type (e.g. a declaration of type pointer to function type)
>   must, as you state above, be a BTF_KIND_FUNC_PROTO.
> In fact, you can tell the difference just from name_off, since
>   a (C-legal) BTF_KIND_FUNC_PROTO will always be anonymous (as
>   the pointee of a pointer type), while a BTF_KIND_FUNC will
>   have the name of the subprogram.

What you stated is true, BTF_KIND_FUNC_PROTO corresponds to
dwarf subroutine tag which has no name while BTF_KIND_FUNC
must have a valid name. The original design is to have both
since they are corresponding to different dwarf constructs.

Martin, what do you think?

> 
> -Ed
> 


Re: [PATCH bpf-next v2 00/13] bpf: add btf func info support

2018-10-17 Thread Yonghong Song


On 10/17/18 4:02 AM, Edward Cree wrote:
> I think the BTF work needs to be better documented; at the moment the only way
>   to determine how BTF sections are structured is to read through the headers,
>   and cross-reference with the DWARF spec to guess at the semantics of various
>   fields.  I've been working on adding BTF support to ebpf_asm, and finding
>   very frustrating the amount of guesswork required.
> Therefore please make sure that each patch extending the BTF format includes
>   documentation patches describing both the layout and the semantics of the 
> new

Make sense. I will add some comments to describe the layout in patch #9.

>   extensions.  For example in patch #9 there is no explanation of
>   btf_ext_header.line_info_off and btf_ext_header.line_info_len (they're not
>   even used by the code, so one cannot reverse-engineer it); while it's fairly
>   clear that they indicate the bounds of the line_info subsection, there is no

The line_info field is added because it is implemented in llvm. I 
imported it to kernel tools directory to be compatible with what llvm 
generates although we did not process it yet. I will add a comment on this.

In the long term, I guess we should add description of format etc.
in Documentation/bpf directory like BTF.rst.

>   specification of what this subsection contains.
> 
> -Ed
> 


[PATCH bpf-next v2 11/13] tools/bpf: refactor to implement btf_get_from_id() in lib/bpf

2018-10-17 Thread Yonghong Song
The function get_btf() is implemented in tools/bpf/bpftool/map.c
to get a btf structure given a map_info. This patch
refactored this function to be function btf_get_from_id()
in tools/lib/bpf so that it can be used later.

Signed-off-by: Yonghong Song 
---
 tools/bpf/bpftool/map.c | 68 ++--
 tools/lib/bpf/btf.c | 69 +
 tools/lib/bpf/btf.h | 18 ++-
 3 files changed, 81 insertions(+), 74 deletions(-)

diff --git a/tools/bpf/bpftool/map.c b/tools/bpf/bpftool/map.c
index 7bf38f0e152e..1b8a75fa0471 100644
--- a/tools/bpf/bpftool/map.c
+++ b/tools/bpf/bpftool/map.c
@@ -215,70 +215,6 @@ static int do_dump_btf(const struct btf_dumper *d,
return ret;
 }
 
-static int get_btf(struct bpf_map_info *map_info, struct btf **btf)
-{
-   struct bpf_btf_info btf_info = { 0 };
-   __u32 len = sizeof(btf_info);
-   __u32 last_size;
-   int btf_fd;
-   void *ptr;
-   int err;
-
-   err = 0;
-   *btf = NULL;
-   btf_fd = bpf_btf_get_fd_by_id(map_info->btf_id);
-   if (btf_fd < 0)
-   return 0;
-
-   /* we won't know btf_size until we call bpf_obj_get_info_by_fd(). so
-* let's start with a sane default - 4KiB here - and resize it only if
-* bpf_obj_get_info_by_fd() needs a bigger buffer.
-*/
-   btf_info.btf_size = 4096;
-   last_size = btf_info.btf_size;
-   ptr = malloc(last_size);
-   if (!ptr) {
-   err = -ENOMEM;
-   goto exit_free;
-   }
-
-   bzero(ptr, last_size);
-   btf_info.btf = ptr_to_u64(ptr);
-   err = bpf_obj_get_info_by_fd(btf_fd, _info, );
-
-   if (!err && btf_info.btf_size > last_size) {
-   void *temp_ptr;
-
-   last_size = btf_info.btf_size;
-   temp_ptr = realloc(ptr, last_size);
-   if (!temp_ptr) {
-   err = -ENOMEM;
-   goto exit_free;
-   }
-   ptr = temp_ptr;
-   bzero(ptr, last_size);
-   btf_info.btf = ptr_to_u64(ptr);
-   err = bpf_obj_get_info_by_fd(btf_fd, _info, );
-   }
-
-   if (err || btf_info.btf_size > last_size) {
-   err = errno;
-   goto exit_free;
-   }
-
-   *btf = btf__new((__u8 *)btf_info.btf, btf_info.btf_size, NULL);
-   if (IS_ERR(*btf)) {
-   err = PTR_ERR(*btf);
-   *btf = NULL;
-   }
-
-exit_free:
-   close(btf_fd);
-   free(ptr);
-
-   return err;
-}
-
 static json_writer_t *get_btf_writer(void)
 {
json_writer_t *jw = jsonw_new(stdout);
@@ -765,7 +701,7 @@ static int do_dump(int argc, char **argv)
 
prev_key = NULL;
 
-   err = get_btf(, );
+   err = btf_get_from_id(info.btf_id, );
if (err) {
p_err("failed to get btf");
goto exit_free;
@@ -909,7 +845,7 @@ static int do_lookup(int argc, char **argv)
}
 
/* here means bpf_map_lookup_elem() succeeded */
-   err = get_btf(, );
+   err = btf_get_from_id(info.btf_id, );
if (err) {
p_err("failed to get btf");
goto exit_free;
diff --git a/tools/lib/bpf/btf.c b/tools/lib/bpf/btf.c
index 4748e0bacd2b..ab654628e966 100644
--- a/tools/lib/bpf/btf.c
+++ b/tools/lib/bpf/btf.c
@@ -42,6 +42,11 @@ struct btf_ext {
__u32 func_info_len;
 };
 
+static inline __u64 ptr_to_u64(const void *ptr)
+{
+   return (__u64) (unsigned long) ptr;
+}
+
 static int btf_add_type(struct btf *btf, struct btf_type *t)
 {
if (btf->types_size - btf->nr_types < 2) {
@@ -403,6 +408,70 @@ const char *btf__name_by_offset(const struct btf *btf, 
__u32 offset)
return NULL;
 }
 
+int btf_get_from_id(__u32 id, struct btf **btf)
+{
+   struct bpf_btf_info btf_info = { 0 };
+   __u32 len = sizeof(btf_info);
+   __u32 last_size;
+   int btf_fd;
+   void *ptr;
+   int err;
+
+   err = 0;
+   *btf = NULL;
+   btf_fd = bpf_btf_get_fd_by_id(id);
+   if (btf_fd < 0)
+   return 0;
+
+   /* we won't know btf_size until we call bpf_obj_get_info_by_fd(). so
+* let's start with a sane default - 4KiB here - and resize it only if
+* bpf_obj_get_info_by_fd() needs a bigger buffer.
+*/
+   btf_info.btf_size = 4096;
+   last_size = btf_info.btf_size;
+   ptr = malloc(last_size);
+   if (!ptr) {
+   err = -ENOMEM;
+   goto exit_free;
+   }
+
+   bzero(ptr, last_size);
+   btf_info.btf = ptr_to_u64(ptr);
+   err = bpf_obj_get_info_by_fd(btf_fd, _info, );
+
+   if (!err && btf_info.btf_size > last_size) {
+   void *temp_ptr;
+
+   last_size = btf_info.btf_size;
+   temp_ptr = realloc(ptr, last_size);
+  

[PATCH bpf-next v2 10/13] tools/bpf: do not use pahole if clang/llvm can generate BTF sections

2018-10-17 Thread Yonghong Song
Add additional checks in tools/testing/selftests/bpf and
samples/bpf such that if clang/llvm compiler can generate
BTF sections, do not use pahole.

Signed-off-by: Yonghong Song 
---
 samples/bpf/Makefile | 8 
 tools/testing/selftests/bpf/Makefile | 8 
 2 files changed, 16 insertions(+)

diff --git a/samples/bpf/Makefile b/samples/bpf/Makefile
index be0a961450bc..870fe7ee2b69 100644
--- a/samples/bpf/Makefile
+++ b/samples/bpf/Makefile
@@ -208,12 +208,20 @@ endif
 BTF_LLC_PROBE := $(shell $(LLC) -march=bpf -mattr=help 2>&1 | grep dwarfris)
 BTF_PAHOLE_PROBE := $(shell $(BTF_PAHOLE) --help 2>&1 | grep BTF)
 BTF_OBJCOPY_PROBE := $(shell $(LLVM_OBJCOPY) --help 2>&1 | grep -i 
'usage.*llvm')
+BTF_LLVM_PROBE := $(shell echo "int main() { return 0; }" | \
+ clang -target bpf -O2 -g -c -x c - -o 
./llvm_btf_verify.o; \
+ readelf -S ./llvm_btf_verify.o | grep BTF; \
+ /bin/rm -f ./llvm_btf_verify.o)
 
+ifneq ($(BTF_LLVM_PROBE),)
+   EXTRA_CFLAGS += -g
+else
 ifneq ($(and $(BTF_LLC_PROBE),$(BTF_PAHOLE_PROBE),$(BTF_OBJCOPY_PROBE)),)
EXTRA_CFLAGS += -g
LLC_FLAGS += -mattr=dwarfris
DWARF2BTF = y
 endif
+endif
 
 # Trick to allow make to be run from this directory
 all:
diff --git a/tools/testing/selftests/bpf/Makefile 
b/tools/testing/selftests/bpf/Makefile
index d99dd6fc3fbe..8d5612724db8 100644
--- a/tools/testing/selftests/bpf/Makefile
+++ b/tools/testing/selftests/bpf/Makefile
@@ -121,7 +121,14 @@ $(OUTPUT)/test_xdp_noinline.o: CLANG_FLAGS += -fno-inline
 BTF_LLC_PROBE := $(shell $(LLC) -march=bpf -mattr=help 2>&1 | grep dwarfris)
 BTF_PAHOLE_PROBE := $(shell $(BTF_PAHOLE) --help 2>&1 | grep BTF)
 BTF_OBJCOPY_PROBE := $(shell $(LLVM_OBJCOPY) --help 2>&1 | grep -i 
'usage.*llvm')
+BTF_LLVM_PROBE := $(shell echo "int main() { return 0; }" | \
+ clang -target bpf -O2 -g -c -x c - -o 
./llvm_btf_verify.o; \
+ readelf -S ./llvm_btf_verify.o | grep BTF; \
+ /bin/rm -f ./llvm_btf_verify.o)
 
+ifneq ($(BTF_LLVM_PROBE),)
+   CLANG_FLAGS += -g
+else
 ifneq ($(BTF_LLC_PROBE),)
 ifneq ($(BTF_PAHOLE_PROBE),)
 ifneq ($(BTF_OBJCOPY_PROBE),)
@@ -131,6 +138,7 @@ ifneq ($(BTF_OBJCOPY_PROBE),)
 endif
 endif
 endif
+endif
 
 $(OUTPUT)/%.o: %.c
$(CLANG) $(CLANG_FLAGS) \
-- 
2.17.1



[PATCH bpf-next v2 13/13] tools/bpf: bpftool: add support for jited func types

2018-10-17 Thread Yonghong Song
This patch added support to print function signature
if btf func_info is available. Note that ksym
now uses function name instead of prog_name as
prog_name has a limit of 16 bytes including
ending '\0'.

The following is a sample output for selftests
test_btf with file test_btf_haskv.o:

  $ bpftool prog dump jited id 1
  int _dummy_tracepoint(struct dummy_tracepoint_args * ):
  bpf_prog_b07ccb89267cf242__dummy_tracepoint:
 0:   push   %rbp
 1:   mov%rsp,%rbp
..
3c:   add$0x28,%rbp
40:   leaveq
41:   retq

  int test_long_fname_1(struct dummy_tracepoint_args * ):
  bpf_prog_2dcecc18072623fc_test_long_fname_1:
 0:   push   %rbp
 1:   mov%rsp,%rbp
..
3a:   add$0x28,%rbp
3e:   leaveq
3f:   retq

  int test_long_fname_2(struct dummy_tracepoint_args * ):
  bpf_prog_89d64e4abf0f0126_test_long_fname_2:
 0:   push   %rbp
 1:   mov%rsp,%rbp
..
80:   add$0x28,%rbp
84:   leaveq
85:   retq

Signed-off-by: Yonghong Song 
---
 tools/bpf/bpftool/btf_dumper.c | 96 ++
 tools/bpf/bpftool/main.h   |  2 +
 tools/bpf/bpftool/prog.c   | 54 +++
 3 files changed, 152 insertions(+)

diff --git a/tools/bpf/bpftool/btf_dumper.c b/tools/bpf/bpftool/btf_dumper.c
index 55bc512a1831..a31df4202335 100644
--- a/tools/bpf/bpftool/btf_dumper.c
+++ b/tools/bpf/bpftool/btf_dumper.c
@@ -249,3 +249,99 @@ int btf_dumper_type(const struct btf_dumper *d, __u32 
type_id,
 {
return btf_dumper_do_type(d, type_id, 0, data);
 }
+
+#define BTF_PRINT_STRING(str)  \
+   {   \
+   pos += snprintf(func_sig + pos, size - pos, str);   \
+   if (pos >= size)\
+   return -1;  \
+   }
+#define BTF_PRINT_ONE_ARG(fmt, arg)\
+   {   \
+   pos += snprintf(func_sig + pos, size - pos, fmt, arg);  \
+   if (pos >= size)\
+   return -1;  \
+   }
+#define BTF_PRINT_TYPE_ONLY(type)  \
+   {   \
+   pos = __btf_dumper_type_only(btf, type, func_sig,   \
+pos, size);\
+   if (pos == -1)  \
+   return -1;  \
+   }
+
+static int __btf_dumper_type_only(struct btf *btf, __u32 type_id,
+ char *func_sig, int pos, int size)
+{
+   const struct btf_type *t = btf__type_by_id(btf, type_id);
+   const struct btf_array *array;
+   int i, vlen;
+
+   switch (BTF_INFO_KIND(t->info)) {
+   case BTF_KIND_INT:
+   BTF_PRINT_ONE_ARG("%s ",
+ btf__name_by_offset(btf, t->name_off));
+   break;
+   case BTF_KIND_STRUCT:
+   BTF_PRINT_ONE_ARG("struct %s ",
+ btf__name_by_offset(btf, t->name_off));
+   break;
+   case BTF_KIND_UNION:
+   BTF_PRINT_ONE_ARG("union %s ",
+ btf__name_by_offset(btf, t->name_off));
+   break;
+   case BTF_KIND_ENUM:
+   BTF_PRINT_ONE_ARG("enum %s ",
+ btf__name_by_offset(btf, t->name_off));
+   break;
+   case BTF_KIND_ARRAY:
+   array = (struct btf_array *)(t + 1);
+   BTF_PRINT_TYPE_ONLY(array->type);
+   BTF_PRINT_ONE_ARG("[%d]", array->nelems);
+   break;
+   case BTF_KIND_PTR:
+   BTF_PRINT_TYPE_ONLY(t->type);
+   BTF_PRINT_STRING("* ");
+   break;
+   case BTF_KIND_UNKN:
+   case BTF_KIND_FWD:
+   case BTF_KIND_TYPEDEF:
+   return -1;
+   case BTF_KIND_VOLATILE:
+   BTF_PRINT_STRING("volatile ");
+   BTF_PRINT_TYPE_ONLY(t->type);
+   break;
+   case BTF_KIND_CONST:
+   BTF_PRINT_STRING("const ");
+   BTF_PRINT_TYPE_ONLY(t->type);
+   break;
+   case BTF_KIND_RESTRICT:
+   BTF_PRINT_STRING("restrict ");
+   BTF_PRINT_TYPE_ONLY(t->type);
+   break;
+   case BTF_KIND_FUNC:
+   case BTF_KIND_FUNC_PROTO:
+   BTF_PRINT_TYPE_ONLY(t->type);
+   BTF_PRINT_ONE_ARG("%s(", btf__name_by_offset

[PATCH bpf-next v2 12/13] tools/bpf: enhance test_btf file testing to test func info

2018-10-17 Thread Yonghong Song
Change the bpf programs test_btf_haskv.c and test_btf_nokv.c to
have two sections, and enhance test_btf.c test_file feature
to test btf func_info returned by the kernel.

Signed-off-by: Yonghong Song 
---
 tools/testing/selftests/bpf/test_btf.c   | 72 +++-
 tools/testing/selftests/bpf/test_btf_haskv.c | 16 -
 tools/testing/selftests/bpf/test_btf_nokv.c  | 16 -
 3 files changed, 99 insertions(+), 5 deletions(-)

diff --git a/tools/testing/selftests/bpf/test_btf.c 
b/tools/testing/selftests/bpf/test_btf.c
index e03a8cea4bb7..0bbefb571426 100644
--- a/tools/testing/selftests/bpf/test_btf.c
+++ b/tools/testing/selftests/bpf/test_btf.c
@@ -2235,10 +2235,16 @@ static int file_has_btf_elf(const char *fn)
 static int do_test_file(unsigned int test_num)
 {
const struct btf_file_test *test = _tests[test_num - 1];
+   const char *expected_fnames[] = {"_dummy_tracepoint",
+"test_long_fname_1",
+"test_long_fname_2"};
+   __u32 func_lens[10], func_types[10], info_len;
+   struct bpf_prog_info info = {};
struct bpf_object *obj = NULL;
struct bpf_program *prog;
+   struct btf *btf = NULL;
struct bpf_map *map;
-   int err;
+   int i, err, prog_fd;
 
fprintf(stderr, "BTF libbpf test[%u] (%s): ", test_num,
test->file);
@@ -2271,6 +2277,7 @@ static int do_test_file(unsigned int test_num)
err = bpf_object__load(obj);
if (CHECK(err < 0, "bpf_object__load: %d", err))
goto done;
+   prog_fd = bpf_program__fd(prog);
 
map = bpf_object__find_map_by_name(obj, "btf_map");
if (CHECK(!map, "btf_map not found")) {
@@ -2285,6 +2292,69 @@ static int do_test_file(unsigned int test_num)
  test->btf_kv_notfound))
goto done;
 
+   if (!jit_enabled)
+   goto skip_jit;
+
+   info_len = sizeof(struct bpf_prog_info);
+   info.nr_jited_func_types = ARRAY_SIZE(func_types);
+   info.nr_jited_func_lens = ARRAY_SIZE(func_lens);
+   info.jited_func_types = ptr_to_u64(_types[0]);
+   info.jited_func_lens = ptr_to_u64(_lens[0]);
+
+   err = bpf_obj_get_info_by_fd(prog_fd, , _len);
+
+   if (CHECK(err == -1, "invalid get info errno:%d", errno)) {
+   fprintf(stderr, "%s\n", btf_log_buf);
+   err = -1;
+   goto done;
+   }
+   if (CHECK(info.nr_jited_func_lens != 3,
+ "incorrect info.nr_jited_func_lens %d",
+ info.nr_jited_func_lens)) {
+   err = -1;
+   goto done;
+   }
+   if (CHECK(info.nr_jited_func_types != 3,
+ "incorrect info.nr_jited_func_types %d",
+ info.nr_jited_func_types)) {
+   err = -1;
+   goto done;
+   }
+   if (CHECK(info.btf_id == 0, "incorrect btf_id = 0")) {
+   err = -1;
+   goto done;
+   }
+
+   err = btf_get_from_id(info.btf_id, );
+   if (CHECK(err, "cannot get btf from kernel, err: %d", err))
+   goto done;
+
+   /* check three functions */
+   for (i = 0; i < 3; i++) {
+   const struct btf_type *t;
+   const char *fname;
+
+   t = btf__type_by_id(btf, func_types[i]);
+   if (CHECK(!t, "btf__type_by_id failure: id %u",
+ func_types[i])) {
+   err = -1;
+   goto done;
+   }
+
+   fname = btf__name_by_offset(btf, t->name_off);
+   err = strcmp(fname, expected_fnames[i]);
+   /* for the second and third functions in .text section,
+* the compiler may order them either way.
+*/
+   if (i && err)
+   err = strcmp(fname, expected_fnames[3 - i]);
+   if (CHECK(err, "incorrect fname %s", fname ? : "")) {
+   err = -1;
+   goto done;
+   }
+   }
+
+skip_jit:
fprintf(stderr, "OK");
 
 done:
diff --git a/tools/testing/selftests/bpf/test_btf_haskv.c 
b/tools/testing/selftests/bpf/test_btf_haskv.c
index b21b876f475d..e5c79fe0ffdb 100644
--- a/tools/testing/selftests/bpf/test_btf_haskv.c
+++ b/tools/testing/selftests/bpf/test_btf_haskv.c
@@ -24,8 +24,8 @@ struct dummy_tracepoint_args {
struct sock *sock;
 };
 
-SEC("dummy_tracepoint")
-int _dummy_tracepoint(struct dummy_tracepoint_args *arg)
+__attribute__((noinline))
+static int test_long_fname_2(struct dummy_tracepoint_args *arg)
 {
struct ipv_counts *counts;
int key = 0;
@@ -42,4 +42,16 @@ int _dummy_tracepoint(struct dummy_tracepoint

[PATCH bpf-next v2 06/13] tools/bpf: sync kernel uapi bpf.h header to tools directory

2018-10-17 Thread Yonghong Song
The kernel uapi bpf.h is synced to tools directory.

Signed-off-by: Yonghong Song 
---
 tools/include/uapi/linux/bpf.h | 11 +++
 1 file changed, 11 insertions(+)

diff --git a/tools/include/uapi/linux/bpf.h b/tools/include/uapi/linux/bpf.h
index f9187b41dff6..7ebbf4f06a65 100644
--- a/tools/include/uapi/linux/bpf.h
+++ b/tools/include/uapi/linux/bpf.h
@@ -332,6 +332,9 @@ union bpf_attr {
 * (context accesses, allowed helpers, etc).
 */
__u32   expected_attach_type;
+   __u32   prog_btf_fd;/* fd pointing to BTF type data 
*/
+   __u32   func_info_len;  /* func_info length */
+   __aligned_u64   func_info;  /* func type info */
};
 
struct { /* anonymous struct used by BPF_OBJ_* commands */
@@ -2585,6 +2588,9 @@ struct bpf_prog_info {
__u32 nr_jited_func_lens;
__aligned_u64 jited_ksyms;
__aligned_u64 jited_func_lens;
+   __u32 btf_id;
+   __u32 nr_jited_func_types;
+   __aligned_u64 jited_func_types;
 } __attribute__((aligned(8)));
 
 struct bpf_map_info {
@@ -2896,4 +2902,9 @@ struct bpf_flow_keys {
};
 };
 
+struct bpf_func_info {
+   __u32   insn_offset;
+   __u32   type_id;
+};
+
 #endif /* _UAPI__LINUX_BPF_H__ */
-- 
2.17.1



[PATCH bpf-next v2 09/13] tools/bpf: add support to read .BTF.ext sections

2018-10-17 Thread Yonghong Song
The .BTF section is already available to encode types.
These types can be used for map
pretty print. The whole .BTF will be passed to the
kernel as well for which kernel can verify and return
to the user space for pretty print etc.

The llvm patch at https://reviews.llvm.org/D53261
will generate .BTF section and one more section
.BTF.ext. The .BTF.ext section encodes function type
information and line information. For line information,
the actual source code is encoded in the section, which
makes compiler itself as an ideal place for section
generation.

The .BTF section does not depend on any other section,
and .BTF.ext has dependency on .BTF for strings and types.

The .BTF section can be directly loaded into the
kernel, and the .BTF.ext section cannot. The loader
may need to do some relocation and merging,
similar to merging multiple code sections, before
loading into the kernel.

In this patch, only func type info is processed.
The functionality is implemented in libbpf.

Signed-off-by: Yonghong Song 
---
 tools/lib/bpf/btf.c| 232 +
 tools/lib/bpf/btf.h|  31 ++
 tools/lib/bpf/libbpf.c |  53 +-
 3 files changed, 312 insertions(+), 4 deletions(-)

diff --git a/tools/lib/bpf/btf.c b/tools/lib/bpf/btf.c
index 33095fc1860b..4748e0bacd2b 100644
--- a/tools/lib/bpf/btf.c
+++ b/tools/lib/bpf/btf.c
@@ -37,6 +37,11 @@ struct btf {
int fd;
 };
 
+struct btf_ext {
+   void *func_info;
+   __u32 func_info_len;
+};
+
 static int btf_add_type(struct btf *btf, struct btf_type *t)
 {
if (btf->types_size - btf->nr_types < 2) {
@@ -397,3 +402,230 @@ const char *btf__name_by_offset(const struct btf *btf, 
__u32 offset)
else
return NULL;
 }
+
+static int btf_ext_validate_func_info(const struct btf_sec_func_info *sinfo,
+ __u32 size, btf_print_fn_t err_log)
+{
+   int sec_hdrlen = sizeof(struct btf_sec_func_info);
+   __u32 record_size = sizeof(struct bpf_func_info);
+   __u32 size_left = size, num_records;
+   __u64 total_record_size;
+
+   while (size_left) {
+   if (size_left < sec_hdrlen) {
+   elog("BTF.ext func_info header not found");
+   return -EINVAL;
+   }
+
+   num_records = sinfo->num_func_info;
+   if (num_records == 0) {
+   elog("incorrect BTF.ext num_func_info");
+   return -EINVAL;
+   }
+
+   total_record_size = sec_hdrlen +
+   (__u64)num_records * record_size;
+   if (size_left < total_record_size) {
+   elog("incorrect BTF.ext num_func_info");
+   return -EINVAL;
+   }
+
+   size_left -= total_record_size;
+   sinfo = (void *)sinfo + total_record_size;
+   }
+
+   return 0;
+}
+static int btf_ext_parse_hdr(__u8 *data, __u32 data_size,
+btf_print_fn_t err_log)
+{
+   const struct btf_ext_header *hdr = (struct btf_ext_header *)data;
+   const struct btf_sec_func_info *sinfo;
+   __u32 meta_left, last_func_info_pos;
+
+   if (data_size < sizeof(*hdr)) {
+   elog("BTF.ext header not found");
+   return -EINVAL;
+   }
+
+   if (hdr->magic != BTF_MAGIC) {
+   elog("Invalid BTF.ext magic:%x\n", hdr->magic);
+   return -EINVAL;
+   }
+
+   if (hdr->version != BTF_VERSION) {
+   elog("Unsupported BTF.ext version:%u\n", hdr->version);
+   return -ENOTSUP;
+   }
+
+   if (hdr->flags) {
+   elog("Unsupported BTF.ext flags:%x\n", hdr->flags);
+   return -ENOTSUP;
+   }
+
+   meta_left = data_size - sizeof(*hdr);
+   if (!meta_left) {
+   elog("BTF.ext has no data\n");
+   return -EINVAL;
+   }
+
+   if (meta_left < hdr->func_info_off) {
+   elog("Invalid BTF.ext func_info section offset:%u\n",
+hdr->func_info_off);
+   return -EINVAL;
+   }
+
+   if (hdr->func_info_off & 0x02) {
+   elog("BTF.ext func_info section is not aligned to 4 bytes\n");
+   return -EINVAL;
+   }
+
+   last_func_info_pos = sizeof(*hdr) + hdr->func_info_off +
+hdr->func_info_len;
+   if (last_func_info_pos > data_size) {
+   elog("Invalid BTF.ext func_info section size:%u\n",
+hdr->func_info_len);
+   return -EINVAL;
+   }
+
+   sinfo = (const struct btf_sec_func_info *)(data + sizeof(*hdr) +
+  hdr->func_

[PATCH bpf-next v2 07/13] tools/bpf: add new fields for program load in lib/bpf

2018-10-17 Thread Yonghong Song
The new fields are added for program load in lib/bpf so
application uses api bpf_load_program_xattr() is able
to load program with btf and func_info data.

This functionality will be used in next patch
by bpf selftest test_btf.

Signed-off-by: Yonghong Song 
---
 tools/lib/bpf/bpf.c | 3 +++
 tools/lib/bpf/bpf.h | 3 +++
 2 files changed, 6 insertions(+)

diff --git a/tools/lib/bpf/bpf.c b/tools/lib/bpf/bpf.c
index d70a255cb05e..d8d48ab34220 100644
--- a/tools/lib/bpf/bpf.c
+++ b/tools/lib/bpf/bpf.c
@@ -196,6 +196,9 @@ int bpf_load_program_xattr(const struct 
bpf_load_program_attr *load_attr,
attr.log_level = 0;
attr.kern_version = load_attr->kern_version;
attr.prog_ifindex = load_attr->prog_ifindex;
+   attr.prog_btf_fd = load_attr->prog_btf_fd;
+   attr.func_info_len = load_attr->func_info_len;
+   attr.func_info = ptr_to_u64(load_attr->func_info);
memcpy(attr.prog_name, load_attr->name,
   min(name_len, BPF_OBJ_NAME_LEN - 1));
 
diff --git a/tools/lib/bpf/bpf.h b/tools/lib/bpf/bpf.h
index 258c3c178333..d2bdaffd7712 100644
--- a/tools/lib/bpf/bpf.h
+++ b/tools/lib/bpf/bpf.h
@@ -74,6 +74,9 @@ struct bpf_load_program_attr {
const char *license;
__u32 kern_version;
__u32 prog_ifindex;
+   __u32 prog_btf_fd;
+   __u32 func_info_len;
+   const struct bpf_func_info *func_info;
 };
 
 /* Flags to direct loading requirements */
-- 
2.17.1



[PATCH bpf-next v2 00/13] bpf: add btf func info support

2018-10-17 Thread Yonghong Song
The BTF support was added to kernel by Commit 69b693f0aefa
("bpf: btf: Introduce BPF Type Format (BTF)"), which introduced
.BTF section into ELF file and is primarily
used for map pretty print.
pahole is used to convert dwarf to BTF for ELF files.

This patch added func info support to the kernel so we can
get better ksym's for bpf function calls. Basically,
pairs of bpf function calls and their corresponding types
are passed to the kernel. Extracting function names from
the types, the kernel is able to construct a ksym for
each function call with embedded function name.

LLVM patch https://reviews.llvm.org/D53261
can generate func info, encoded in .BTF.ext ELF section.
In addition, it also added support for FUNC and FUNC_PROTO
types, which are also supported through this patch set.
The following is an example to show FUNC and
FUNC_PROTO difference, compiled with the above LLVM patch
with Debug mode.

  -bash-4.2$ cat test.c
  int foo(int (*bar)(int)) { return bar(5); }
  -bash-4.2$ clang -target bpf -g -O2 -mllvm -debug-only=btf -c test.c
  Type Table:
  [1] FUNC name_off=1 info=0x0c01 size/type=2
param_type=3
  [2] INT name_off=11 info=0x0100 size/type=4
desc=0x0120
  [3] PTR name_off=0 info=0x0200 size/type=4
  [4] FUNC_PROTO name_off=0 info=0x0d01 size/type=2
param_type=2
  
  String Table:
  0 :
  1 : foo
  5 : .text
  11 : int
  15 : test.c
  22 : int foo(int (*bar)(int)) { return bar(5); }
  
  FuncInfo Table:
  sec_name_off=5
insn_offset= type_id=1
  ...

In the above, type and string tables are in .BTF section and
the func info in .BTF.ext. The "" is the
insn offset which is not available during the dump time but
resolved during later compilation process.
Following the format specification at Patch #9 and examine the
raw data in .BTF.ext section, we have
  FuncInfo Table:
  sec_name_off=5
insn_offset=0 type_id=1
The (insn_offset, type_id) can be passed to the kernel
so the kernel can find the func name and use it in the ksym.
Below is a demonstration from Patch #13.
  $ bpftool prog dump jited id 1
  int _dummy_tracepoint(struct dummy_tracepoint_args * ):
  bpf_prog_b07ccb89267cf242__dummy_tracepoint:
 0:   push   %rbp
 1:   mov%rsp,%rbp
..
3c:   add$0x28,%rbp
40:   leaveq
41:   retq
  
  int test_long_fname_1(struct dummy_tracepoint_args * ):
  bpf_prog_2dcecc18072623fc_test_long_fname_1:
 0:   push   %rbp
 1:   mov%rsp,%rbp
..
3a:   add$0x28,%rbp
3e:   leaveq
3f:   retq
  
  int test_long_fname_2(struct dummy_tracepoint_args * ):
  bpf_prog_89d64e4abf0f0126_test_long_fname_2:
 0:   push   %rbp
 1:   mov%rsp,%rbp
..
80:   add$0x28,%rbp
84:   leaveq
85:   retq

For the patchset,
Patch #1  refactors the code to break up btf_type_is_void().
Patch #2  introduces new BTF types BTF_KIND_FUNC and BTF_KIND_FUNC_PROTO.
Patch #3  syncs btf.h header to tools directory.
Patch #4  adds btf func/func_proto self tests in test_btf.
Patch #5  adds kernel interface to load func_info to kernel
  and pass func_info to userspace.
Patch #6  syncs bpf.h header to tools directory.
Patch #7  adds news btf/func_info related fields in libbpf
  program load function.
Patch #8  extends selftest test_btf to test load/retrieve func_type info.
Patch #9  adds .BTF.ext func info support.
Patch #10 changes Makefile to avoid using pahole if llvm is capable of
  generating BTF sections.
Patch #11 refactors to have btf_get_from_id() in libbpf for reuse.
Patch #12 enhance test_btf file testing to test func info.
Patch #13 adds bpftool support for func signature dump.

Yonghong Song (13):
  bpf: btf: Break up btf_type_is_void()
  bpf: btf: Add BTF_KIND_FUNC and BTF_KIND_FUNC_PROTO
  tools/bpf: sync kernel btf.h header
  tools/bpf: add btf func/func_proto unit tests in selftest test_btf
  bpf: get better bpf_prog ksyms based on btf func type_id
  tools/bpf: sync kernel uapi bpf.h header to tools directory
  tools/bpf: add new fields for program load in lib/bpf
  tools/bpf: extends test_btf to test load/retrieve func_type info
  tools/bpf: add support to read .BTF.ext sections
  tools/bpf: do not use pahole if clang/llvm can generate BTF sections
  tools/bpf: refactor to implement btf_get_from_id() in lib/bpf
  tools/bpf: enhance test_btf file testing to test func info
  tools/bpf: bpftool: add support for jited func types

Changelogs:
  v1 -> v2:
. Added missing sign-off
. Limited the func_name/struct_member_name length for validity test
. Removed/changed several verifier messages
. Modified several commit messages to remove line_off reference

 include/linux/bpf.h  |   2 +
 include/linux/bpf_verifier.h |   1 +
 include/linux/btf.h  |   2 +
 include/uapi/linux/bpf.h   

[PATCH bpf-next v2 01/13] bpf: btf: Break up btf_type_is_void()

2018-10-17 Thread Yonghong Song
This patch breaks up btf_type_is_void() into
btf_type_is_void() and btf_type_is_fwd().

It also adds btf_type_nosize() to better describe it is
testing a type has nosize info.

Signed-off-by: Martin KaFai Lau 
Signed-off-by: Yonghong Song 
---
 kernel/bpf/btf.c | 37 ++---
 1 file changed, 22 insertions(+), 15 deletions(-)

diff --git a/kernel/bpf/btf.c b/kernel/bpf/btf.c
index 378cef70341c..be406d8906ce 100644
--- a/kernel/bpf/btf.c
+++ b/kernel/bpf/btf.c
@@ -306,15 +306,22 @@ static bool btf_type_is_modifier(const struct btf_type *t)
 
 static bool btf_type_is_void(const struct btf_type *t)
 {
-   /* void => no type and size info.
-* Hence, FWD is also treated as void.
-*/
-   return t == _void || BTF_INFO_KIND(t->info) == BTF_KIND_FWD;
+   return t == _void;
+}
+
+static bool btf_type_is_fwd(const struct btf_type *t)
+{
+   return BTF_INFO_KIND(t->info) == BTF_KIND_FWD;
+}
+
+static bool btf_type_nosize(const struct btf_type *t)
+{
+   return btf_type_is_void(t) || btf_type_is_fwd(t);
 }
 
-static bool btf_type_is_void_or_null(const struct btf_type *t)
+static bool btf_type_nosize_or_null(const struct btf_type *t)
 {
-   return !t || btf_type_is_void(t);
+   return !t || btf_type_nosize(t);
 }
 
 /* union is only a special case of struct:
@@ -826,7 +833,7 @@ const struct btf_type *btf_type_id_size(const struct btf 
*btf,
u32 size = 0;
 
size_type = btf_type_by_id(btf, size_type_id);
-   if (btf_type_is_void_or_null(size_type))
+   if (btf_type_nosize_or_null(size_type))
return NULL;
 
if (btf_type_has_size(size_type)) {
@@ -842,7 +849,7 @@ const struct btf_type *btf_type_id_size(const struct btf 
*btf,
size = btf->resolved_sizes[size_type_id];
size_type_id = btf->resolved_ids[size_type_id];
size_type = btf_type_by_id(btf, size_type_id);
-   if (btf_type_is_void(size_type))
+   if (btf_type_nosize_or_null(size_type))
return NULL;
}
 
@@ -1164,7 +1171,7 @@ static int btf_modifier_resolve(struct btf_verifier_env 
*env,
}
 
/* "typedef void new_void", "const void"...etc */
-   if (btf_type_is_void(next_type))
+   if (btf_type_is_void(next_type) || btf_type_is_fwd(next_type))
goto resolved;
 
if (!env_type_is_resolve_sink(env, next_type) &&
@@ -1178,7 +1185,7 @@ static int btf_modifier_resolve(struct btf_verifier_env 
*env,
 * pretty print).
 */
if (!btf_type_id_size(btf, _type_id, _type_size) &&
-   !btf_type_is_void(btf_type_id_resolve(btf, _type_id))) {
+   !btf_type_nosize(btf_type_id_resolve(btf, _type_id))) {
btf_verifier_log_type(env, v->t, "Invalid type_id");
return -EINVAL;
}
@@ -1205,7 +1212,7 @@ static int btf_ptr_resolve(struct btf_verifier_env *env,
}
 
/* "void *" */
-   if (btf_type_is_void(next_type))
+   if (btf_type_is_void(next_type) || btf_type_is_fwd(next_type))
goto resolved;
 
if (!env_type_is_resolve_sink(env, next_type) &&
@@ -1235,7 +1242,7 @@ static int btf_ptr_resolve(struct btf_verifier_env *env,
}
 
if (!btf_type_id_size(btf, _type_id, _type_size) &&
-   !btf_type_is_void(btf_type_id_resolve(btf, _type_id))) {
+   !btf_type_nosize(btf_type_id_resolve(btf, _type_id))) {
btf_verifier_log_type(env, v->t, "Invalid type_id");
return -EINVAL;
}
@@ -1396,7 +1403,7 @@ static int btf_array_resolve(struct btf_verifier_env *env,
/* Check array->index_type */
index_type_id = array->index_type;
index_type = btf_type_by_id(btf, index_type_id);
-   if (btf_type_is_void_or_null(index_type)) {
+   if (btf_type_nosize_or_null(index_type)) {
btf_verifier_log_type(env, v->t, "Invalid index");
return -EINVAL;
}
@@ -1415,7 +1422,7 @@ static int btf_array_resolve(struct btf_verifier_env *env,
/* Check array->type */
elem_type_id = array->type;
elem_type = btf_type_by_id(btf, elem_type_id);
-   if (btf_type_is_void_or_null(elem_type)) {
+   if (btf_type_nosize_or_null(elem_type)) {
btf_verifier_log_type(env, v->t,
  "Invalid elem");
return -EINVAL;
@@ -1615,7 +1622,7 @@ static int btf_struct_resolve(struct btf_verifier_env 
*env,
const struct btf_type *member_type = btf_type_by_id(env->btf,
member_type_id);
 
-   if (btf_type_is_void_or_null(member_type)) {
+   if (btf_type_nosize_or_null(me

[PATCH bpf-next v2 03/13] tools/bpf: sync kernel btf.h header

2018-10-17 Thread Yonghong Song
The kernel uapi btf.h is synced to the tools directory.

Signed-off-by: Martin KaFai Lau 
Signed-off-by: Yonghong Song 
---
 tools/include/uapi/linux/btf.h | 9 ++---
 1 file changed, 6 insertions(+), 3 deletions(-)

diff --git a/tools/include/uapi/linux/btf.h b/tools/include/uapi/linux/btf.h
index 972265f32871..63f8500e6f34 100644
--- a/tools/include/uapi/linux/btf.h
+++ b/tools/include/uapi/linux/btf.h
@@ -40,7 +40,8 @@ struct btf_type {
/* "size" is used by INT, ENUM, STRUCT and UNION.
 * "size" tells the size of the type it is describing.
 *
-* "type" is used by PTR, TYPEDEF, VOLATILE, CONST and RESTRICT.
+* "type" is used by PTR, TYPEDEF, VOLATILE, CONST, RESTRICT,
+* FUNC and FUNC_PROTO.
 * "type" is a type_id referring to another type.
 */
union {
@@ -64,8 +65,10 @@ struct btf_type {
 #define BTF_KIND_VOLATILE  9   /* Volatile */
 #define BTF_KIND_CONST 10  /* Const*/
 #define BTF_KIND_RESTRICT  11  /* Restrict */
-#define BTF_KIND_MAX   11
-#define NR_BTF_KINDS   12
+#define BTF_KIND_FUNC  12  /* Function */
+#define BTF_KIND_FUNC_PROTO13  /* Function Prototype   */
+#define BTF_KIND_MAX   13
+#define NR_BTF_KINDS   14
 
 /* For some specific BTF_KIND, "struct btf_type" is immediately
  * followed by extra data.
-- 
2.17.1



[PATCH bpf-next v2 08/13] tools/bpf: extends test_btf to test load/retrieve func_type info

2018-10-17 Thread Yonghong Song
A two function bpf program is loaded with btf and func_info.
After successful prog load, the bpf_get_info syscall is called
to retrieve prog info to ensure the types returned from the
kernel matches the types passed to the kernel from the
user space.

Several negative tests are also added to test loading/retriving
of func_type info.

Signed-off-by: Yonghong Song 
---
 tools/testing/selftests/bpf/test_btf.c | 278 -
 1 file changed, 275 insertions(+), 3 deletions(-)

diff --git a/tools/testing/selftests/bpf/test_btf.c 
b/tools/testing/selftests/bpf/test_btf.c
index b6461c3c5e11..e03a8cea4bb7 100644
--- a/tools/testing/selftests/bpf/test_btf.c
+++ b/tools/testing/selftests/bpf/test_btf.c
@@ -5,6 +5,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -22,9 +23,13 @@
 #include "bpf_rlimit.h"
 #include "bpf_util.h"
 
+#define MAX_INSNS  512
+#define MAX_SUBPROGS   16
+
 static uint32_t pass_cnt;
 static uint32_t error_cnt;
 static uint32_t skip_cnt;
+static bool jit_enabled;
 
 #define CHECK(condition, format...) ({ \
int __ret = !!(condition);  \
@@ -60,6 +65,24 @@ static int __base_pr(const char *format, ...)
return err;
 }
 
+static bool is_jit_enabled(void)
+{
+   const char *jit_sysctl = "/proc/sys/net/core/bpf_jit_enable";
+   bool enabled = false;
+   int sysctl_fd;
+
+   sysctl_fd = open(jit_sysctl, 0, O_RDONLY);
+   if (sysctl_fd != -1) {
+   char tmpc;
+
+   if (read(sysctl_fd, , sizeof(tmpc)) == 1)
+   enabled = (tmpc != '0');
+   close(sysctl_fd);
+   }
+
+   return enabled;
+}
+
 #define BTF_INFO_ENC(kind, root, vlen) \
((!!(root) << 31) | ((kind) << 24) | ((vlen) & BTF_MAX_VLEN))
 
@@ -103,6 +126,7 @@ static struct args {
bool get_info_test;
bool pprint_test;
bool always_log;
+   bool func_type_test;
 } args;
 
 static char btf_log_buf[BTF_LOG_BUF_SIZE];
@@ -2693,16 +2717,256 @@ static int test_pprint(void)
return err;
 }
 
+static struct btf_func_type_test {
+   const char *descr;
+   const char *str_sec;
+   __u32 raw_types[MAX_NR_RAW_TYPES];
+   __u32 str_sec_size;
+   struct bpf_insn insns[MAX_INSNS];
+   __u32 prog_type;
+   struct bpf_func_info func_info[MAX_SUBPROGS];
+   __u32 func_info_len;
+   bool expected_prog_load_failure;
+} func_type_test[] = {
+
+{
+   .descr = "func_type test #1",
+   .str_sec = "\0int\0unsigned int\0funcA\0funcB",
+   .raw_types = {
+   BTF_TYPE_INT_ENC(NAME_TBD, BTF_INT_SIGNED, 0, 32, 4),  /* [1] */
+   BTF_TYPE_INT_ENC(NAME_TBD, 0, 0, 32, 4),   /* [2] */
+   BTF_TYPE_ENC(NAME_TBD, BTF_INFO_ENC(BTF_KIND_FUNC, 0, 2), 1),  
/* [3] */
+   1, 2,
+   BTF_TYPE_ENC(NAME_TBD, BTF_INFO_ENC(BTF_KIND_FUNC, 0, 2), 1),  
/* [4] */
+   2, 1,
+   BTF_END_RAW,
+   },
+   .str_sec_size = sizeof("\0int\0unsigned int\0funcA\0funcB"),
+   .insns = {
+   BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 1, 0, 2),
+   BPF_MOV64_IMM(BPF_REG_0, 1),
+   BPF_EXIT_INSN(),
+   BPF_MOV64_IMM(BPF_REG_0, 2),
+   BPF_EXIT_INSN(),
+   },
+   .prog_type = BPF_PROG_TYPE_TRACEPOINT,
+   .func_info = { {0, 3}, {3, 4} },
+   .func_info_len = 2 * sizeof(struct bpf_func_info),
+},
+
+{
+   .descr = "func_type test #2",
+   .str_sec = "\0int\0unsigned int\0funcA\0funcB",
+   .raw_types = {
+   BTF_TYPE_INT_ENC(NAME_TBD, BTF_INT_SIGNED, 0, 32, 4),  /* [1] */
+   BTF_TYPE_INT_ENC(NAME_TBD, 0, 0, 32, 4),   /* [2] */
+   /* incorrect func type */
+   BTF_TYPE_ENC(NAME_TBD, BTF_INFO_ENC(BTF_KIND_FUNC_PROTO, 0, 2), 
1),  /* [3] */
+   1, 2,
+   BTF_TYPE_ENC(NAME_TBD, BTF_INFO_ENC(BTF_KIND_FUNC, 0, 2), 1),  
/* [4] */
+   2, 1,
+   BTF_END_RAW,
+   },
+   .str_sec_size = sizeof("\0int\0unsigned int\0funcA\0funcB"),
+   .insns = {
+   BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 1, 0, 2),
+   BPF_MOV64_IMM(BPF_REG_0, 1),
+   BPF_EXIT_INSN(),
+   BPF_MOV64_IMM(BPF_REG_0, 2),
+   BPF_EXIT_INSN(),
+   },
+   .prog_type = BPF_PROG_TYPE_TRACEPOINT,
+   .func_info = { {0, 3}, {3, 4} },
+   .func_info_len = 2 * sizeof(struct bpf_func_info),
+   .expected_prog_load_failure = true,
+},
+
+{
+   .descr = "func_type test #3",
+   .str_sec = "\0int\0unsigned int\0funcA\0funcB",
+   .raw_types = {
+   BTF_TYPE_INT_ENC(NAME_TBD, BTF_INT_SIGNED, 0, 32, 4),  /* [1] */
+ 

[PATCH bpf-next v2 05/13] bpf: get better bpf_prog ksyms based on btf func type_id

2018-10-17 Thread Yonghong Song
This patch added interface to load a program with the following
additional information:
   . prog_btf_fd
   . func_info and func_info_len
where func_info will provides function range and type_id
corresponding to each function.

If verifier agrees with function range provided by the user,
the bpf_prog ksym for each function will use the func name
provided in the type_id, which is supposed to provide better
encoding as it is not limited by 16 bytes program name
limitation and this is better for bpf program which contains
multiple subprograms.

The bpf_prog_info interface is also extended to
return btf_id and jited_func_types, so user spaces can
print out the function prototype for each jited function.

Signed-off-by: Yonghong Song 
---
 include/linux/bpf.h  |  2 +
 include/linux/bpf_verifier.h |  1 +
 include/linux/btf.h  |  2 +
 include/uapi/linux/bpf.h | 11 +
 kernel/bpf/btf.c | 16 +++
 kernel/bpf/core.c| 10 +
 kernel/bpf/syscall.c | 83 +++-
 kernel/bpf/verifier.c| 46 
 8 files changed, 170 insertions(+), 1 deletion(-)

diff --git a/include/linux/bpf.h b/include/linux/bpf.h
index e60fff48288b..a99e038ce9c4 100644
--- a/include/linux/bpf.h
+++ b/include/linux/bpf.h
@@ -308,6 +308,8 @@ struct bpf_prog_aux {
void *security;
 #endif
struct bpf_prog_offload *offload;
+   struct btf *btf;
+   u32 type_id; /* type id for this prog/func */
union {
struct work_struct work;
struct rcu_head rcu;
diff --git a/include/linux/bpf_verifier.h b/include/linux/bpf_verifier.h
index 9e8056ec20fa..e84782ec50ac 100644
--- a/include/linux/bpf_verifier.h
+++ b/include/linux/bpf_verifier.h
@@ -201,6 +201,7 @@ static inline bool bpf_verifier_log_needed(const struct 
bpf_verifier_log *log)
 struct bpf_subprog_info {
u32 start; /* insn idx of function entry point */
u16 stack_depth; /* max. stack depth used by this function */
+   u32 type_id; /* btf type_id for this subprog */
 };
 
 /* single container for all structs
diff --git a/include/linux/btf.h b/include/linux/btf.h
index e076c4697049..4611a53b5dd7 100644
--- a/include/linux/btf.h
+++ b/include/linux/btf.h
@@ -46,5 +46,7 @@ void btf_type_seq_show(const struct btf *btf, u32 type_id, 
void *obj,
   struct seq_file *m);
 int btf_get_fd_by_id(u32 id);
 u32 btf_id(const struct btf *btf);
+bool btf_type_id_func(const struct btf *btf, u32 type_id);
+const char *btf_get_name_by_id(const struct btf *btf, u32 type_id);
 
 #endif
diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h
index f9187b41dff6..7ebbf4f06a65 100644
--- a/include/uapi/linux/bpf.h
+++ b/include/uapi/linux/bpf.h
@@ -332,6 +332,9 @@ union bpf_attr {
 * (context accesses, allowed helpers, etc).
 */
__u32   expected_attach_type;
+   __u32   prog_btf_fd;/* fd pointing to BTF type data 
*/
+   __u32   func_info_len;  /* func_info length */
+   __aligned_u64   func_info;  /* func type info */
};
 
struct { /* anonymous struct used by BPF_OBJ_* commands */
@@ -2585,6 +2588,9 @@ struct bpf_prog_info {
__u32 nr_jited_func_lens;
__aligned_u64 jited_ksyms;
__aligned_u64 jited_func_lens;
+   __u32 btf_id;
+   __u32 nr_jited_func_types;
+   __aligned_u64 jited_func_types;
 } __attribute__((aligned(8)));
 
 struct bpf_map_info {
@@ -2896,4 +2902,9 @@ struct bpf_flow_keys {
};
 };
 
+struct bpf_func_info {
+   __u32   insn_offset;
+   __u32   type_id;
+};
+
 #endif /* _UAPI__LINUX_BPF_H__ */
diff --git a/kernel/bpf/btf.c b/kernel/bpf/btf.c
index 763f8e06bc91..9e97bbbafe9b 100644
--- a/kernel/bpf/btf.c
+++ b/kernel/bpf/btf.c
@@ -489,6 +489,15 @@ static const struct btf_type *btf_type_by_id(const struct 
btf *btf, u32 type_id)
return btf->types[type_id];
 }
 
+bool btf_type_id_func(const struct btf *btf, u32 type_id)
+{
+   const struct btf_type *type = btf_type_by_id(btf, type_id);
+
+   if (!type || !btf_type_is_func(type))
+   return false;
+   return true;
+}
+
 /*
  * Regular int is not a bit field and it must be either
  * u8/u16/u32/u64.
@@ -2582,3 +2591,10 @@ u32 btf_id(const struct btf *btf)
 {
return btf->id;
 }
+
+const char *btf_get_name_by_id(const struct btf *btf, u32 type_id)
+{
+   const struct btf_type *t = btf_type_by_id(btf, type_id);
+
+   return btf_name_by_offset(btf, t->name_off);
+}
diff --git a/kernel/bpf/core.c b/kernel/bpf/core.c
index defcf4df6d91..f5ba5d4cb259 100644
--- a/kernel/bpf/core.c
+++ b/kernel/bpf/core.c
@@ -27,6 +27,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -387,6 +388,7 @@ bpf_get_prog_addr_region(const struct bpf_prog *prog,
 static void bpf_get_prog_name(const struct bpf_p

[PATCH bpf-next v2 02/13] bpf: btf: Add BTF_KIND_FUNC and BTF_KIND_FUNC_PROTO

2018-10-17 Thread Yonghong Song
This patch adds BTF_KIND_FUNC and BTF_KIND_FUNC_PROTO
support to the type section. BTF_KIND_FUNC_PROTO is used
to specify the type of a function pointer. With this,
BTF has a complete set of C types (except float).

BTF_KIND_FUNC is used to specify the signature of a
defined subprogram. BTF_KIND_FUNC_PROTO can be referenced
by another type, e.g., a pointer type, and BTF_KIND_FUNC
type cannot be referenced by another type.

For both BTF_KIND_FUNC and BTF_KIND_FUNC_PROTO types,
the func return type is in t->type (where t is a
"struct btf_type" object). The func args are an array of
u32s immediately following object "t".

As a concrete example, for the C program below,
  $ cat test.c
  int foo(int (*bar)(int)) { return bar(5); }
with LLVM patch https://reviews.llvm.org/D53261
in Debug mode, we have
  $ clang -target bpf -g -O2 -mllvm -debug-only=btf -c test.c
  Type Table:
  [1] FUNC NameOff=1 Info=0x0c01 Size/Type=2
  ParamType=3
  [2] INT NameOff=11 Info=0x0100 Size/Type=4
  Desc=0x0120
  [3] PTR NameOff=0 Info=0x0200 Size/Type=4
  [4] FUNC_PROTO NameOff=0 Info=0x0d01 Size/Type=2
  ParamType=2

  String Table:
  0 :
  1 : foo
  5 : .text
  11 : int
  15 : test.c
  22 : int foo(int (*bar)(int)) { return bar(5); }

  FuncInfo Table:
  SecNameOff=5
  InsnOffset= TypeId=1

  ...

(Eventually we shall have bpftool to dump btf information
 like the above.)

Function "foo" has a FUNC type (type_id = 1).
The parameter of "foo" has type_id 3 which is PTR->FUNC_PROTO,
where FUNC_PROTO refers to function pointer "bar".

In FuncInfo Table, for section .text, the function,
with to-be-determined offset (marked as ),
has type_id=1 which refers to a FUNC type.
This way, the function signature is
available to both kernel and user space.
Here, the insn offset is not available during the dump time
as relocation is resolved pretty late in the compilation process.

Signed-off-by: Martin KaFai Lau 
Signed-off-by: Yonghong Song 
---
 include/uapi/linux/btf.h |   9 +-
 kernel/bpf/btf.c | 280 ++-
 2 files changed, 253 insertions(+), 36 deletions(-)

diff --git a/include/uapi/linux/btf.h b/include/uapi/linux/btf.h
index 972265f32871..63f8500e6f34 100644
--- a/include/uapi/linux/btf.h
+++ b/include/uapi/linux/btf.h
@@ -40,7 +40,8 @@ struct btf_type {
/* "size" is used by INT, ENUM, STRUCT and UNION.
 * "size" tells the size of the type it is describing.
 *
-* "type" is used by PTR, TYPEDEF, VOLATILE, CONST and RESTRICT.
+* "type" is used by PTR, TYPEDEF, VOLATILE, CONST, RESTRICT,
+* FUNC and FUNC_PROTO.
 * "type" is a type_id referring to another type.
 */
union {
@@ -64,8 +65,10 @@ struct btf_type {
 #define BTF_KIND_VOLATILE  9   /* Volatile */
 #define BTF_KIND_CONST 10  /* Const*/
 #define BTF_KIND_RESTRICT  11  /* Restrict */
-#define BTF_KIND_MAX   11
-#define NR_BTF_KINDS   12
+#define BTF_KIND_FUNC  12  /* Function */
+#define BTF_KIND_FUNC_PROTO13  /* Function Prototype   */
+#define BTF_KIND_MAX   13
+#define NR_BTF_KINDS   14
 
 /* For some specific BTF_KIND, "struct btf_type" is immediately
  * followed by extra data.
diff --git a/kernel/bpf/btf.c b/kernel/bpf/btf.c
index be406d8906ce..763f8e06bc91 100644
--- a/kernel/bpf/btf.c
+++ b/kernel/bpf/btf.c
@@ -5,6 +5,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -259,6 +260,8 @@ static const char * const btf_kind_str[NR_BTF_KINDS] = {
[BTF_KIND_VOLATILE] = "VOLATILE",
[BTF_KIND_CONST]= "CONST",
[BTF_KIND_RESTRICT] = "RESTRICT",
+   [BTF_KIND_FUNC] = "FUNC",
+   [BTF_KIND_FUNC_PROTO]   = "FUNC_PROTO",
 };
 
 struct btf_kind_operations {
@@ -281,6 +284,9 @@ struct btf_kind_operations {
 static const struct btf_kind_operations * const kind_ops[NR_BTF_KINDS];
 static struct btf_type btf_void;
 
+static int btf_resolve(struct btf_verifier_env *env,
+  const struct btf_type *t, u32 type_id);
+
 static bool btf_type_is_modifier(const struct btf_type *t)
 {
/* Some of them is not strictly a C modifier
@@ -314,9 +320,20 @@ static bool btf_type_is_fwd(const struct btf_type *t)
return BTF_INFO_KIND(t->info) == BTF_KIND_FWD;
 }
 
+static bool btf_type_is_func(const struct btf_type *t)
+{
+   return BTF_INFO_KIND(t->info) == BTF_KIND_FUNC;
+}
+
+static bool btf_type_is_func_proto(const struct btf_type *t)
+{
+   return BTF_INFO_KIND(t->info) == BTF_KIND_FUNC_PROTO;
+}
+
 static bool btf_type_nosize(const struct btf_type *t)
 {
-   return btf_type_is_void(t) || btf_type_is_fwd(t);
+   return btf_type_is_

[PATCH bpf-next v2 04/13] tools/bpf: add btf func/func_proto unit tests in selftest test_btf

2018-10-17 Thread Yonghong Song
Add several BTF_KIND_FUNC and BTF_KIND_FUNC_PROTO
unit tests in bpf selftest test_btf.

Signed-off-by: Martin KaFai Lau 
Signed-off-by: Yonghong Song 
---
 tools/lib/bpf/btf.c|   4 +
 tools/testing/selftests/bpf/test_btf.c | 216 +
 2 files changed, 220 insertions(+)

diff --git a/tools/lib/bpf/btf.c b/tools/lib/bpf/btf.c
index 449591aa9900..33095fc1860b 100644
--- a/tools/lib/bpf/btf.c
+++ b/tools/lib/bpf/btf.c
@@ -165,6 +165,10 @@ static int btf_parse_type_sec(struct btf *btf, 
btf_print_fn_t err_log)
case BTF_KIND_ENUM:
next_type += vlen * sizeof(struct btf_enum);
break;
+   case BTF_KIND_FUNC:
+   case BTF_KIND_FUNC_PROTO:
+   next_type += vlen * sizeof(int);
+   break;
case BTF_KIND_TYPEDEF:
case BTF_KIND_PTR:
case BTF_KIND_FWD:
diff --git a/tools/testing/selftests/bpf/test_btf.c 
b/tools/testing/selftests/bpf/test_btf.c
index f42b3396d622..b6461c3c5e11 100644
--- a/tools/testing/selftests/bpf/test_btf.c
+++ b/tools/testing/selftests/bpf/test_btf.c
@@ -1374,6 +1374,222 @@ static struct btf_raw_test raw_tests[] = {
.map_create_err = true,
 },
 
+{
+   .descr = "func pointer #1",
+   .raw_types = {
+   BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4),  /* [1] */
+   BTF_TYPE_INT_ENC(0, 0, 0, 32, 4),   /* [2] */
+   /* int (*func)(int, unsigned int) */
+   BTF_TYPE_ENC(0, BTF_INFO_ENC(BTF_KIND_FUNC_PROTO, 0, 2), 1),
/* [3] */
+   1, 2,
+   BTF_TYPE_ENC(0, BTF_INFO_ENC(BTF_KIND_PTR, 0, 0), 3),   /* [4] 
*/
+   BTF_END_RAW,
+   },
+   .str_sec = "",
+   .str_sec_size = sizeof(""),
+   .map_type = BPF_MAP_TYPE_ARRAY,
+   .map_name = "func_type_check_btf",
+   .key_size = sizeof(int),
+   .value_size = sizeof(int),
+   .key_type_id = 1,
+   .value_type_id = 1,
+   .max_entries = 4,
+},
+
+{
+   .descr = "func pointer #2",
+   .raw_types = {
+   BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4),  /* [1] */
+   BTF_TYPE_INT_ENC(0, 0, 0, 32, 4),   /* [2] */
+   /* void (*func)(int, unsigned int, ) */
+   BTF_TYPE_ENC(0, BTF_INFO_ENC(BTF_KIND_FUNC_PROTO, 0, 3), 0),
/* [3] */
+   1, 2, 0,
+   BTF_TYPE_ENC(0, BTF_INFO_ENC(BTF_KIND_PTR, 0, 0), 3),   /* [4] 
*/
+   BTF_END_RAW,
+   },
+   .str_sec = "",
+   .str_sec_size = sizeof(""),
+   .map_type = BPF_MAP_TYPE_ARRAY,
+   .map_name = "func_type_check_btf",
+   .key_size = sizeof(int),
+   .value_size = sizeof(int),
+   .key_type_id = 1,
+   .value_type_id = 1,
+   .max_entries = 4,
+},
+
+{
+   .descr = "func pointer #3",
+   .raw_types = {
+   BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4),  /* [1] */
+   BTF_TYPE_INT_ENC(0, 0, 0, 32, 4),   /* [2] */
+   /* void (*func)(void, int, unsigned int) */
+   BTF_TYPE_ENC(0, BTF_INFO_ENC(BTF_KIND_FUNC_PROTO, 0, 3), 0),
/* [3] */
+   1, 0, 2,
+   BTF_TYPE_ENC(0, BTF_INFO_ENC(BTF_KIND_PTR, 0, 0), 3),   /* [4] 
*/
+   BTF_END_RAW,
+   },
+   .str_sec = "",
+   .str_sec_size = sizeof(""),
+   .map_type = BPF_MAP_TYPE_ARRAY,
+   .map_name = "func_type_check_btf",
+   .key_size = sizeof(int),
+   .value_size = sizeof(int),
+   .key_type_id = 1,
+   .value_type_id = 1,
+   .max_entries = 4,
+   .btf_load_err = true,
+   .err_str = "Invalid arg#2",
+},
+
+{
+   .descr = "func pointer #4",
+   .raw_types = {
+   BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4),  /* [1] */
+   BTF_TYPE_INT_ENC(0, 0, 0, 32, 4),   /* [2] */
+   /*
+* Testing:
+* BTF_KIND_CONST => BTF_KIND_TYPEDEF => BTF_KIND_PTR =>
+* BTF_KIND_FUNC_PROTO
+*/
+   /* typedef void (*func_ptr)(int, unsigned int) */
+   BTF_TYPE_ENC(0, BTF_INFO_ENC(BTF_KIND_TYPEDEF, 0, 0), 5),/* [3] 
*/
+   /* const func_ptr */
+   BTF_TYPE_ENC(0, BTF_INFO_ENC(BTF_KIND_CONST, 0, 0), 3), /* [4] 
*/
+   BTF_TYPE_ENC(0, BTF_INFO_ENC(BTF_KIND_PTR, 0, 0), 6),   /* [5] 
*/
+   BTF_TYPE_ENC(0, BTF_INFO_ENC(BTF_KIND_FUNC_PROTO, 0, 2), 0),
/* [6] */
+   1, 2,
+   BTF_END_RAW,
+   },
+   .str_sec = "",
+   .str_sec_size = sizeof(""),
+   .map_type = BPF_MAP_TYPE_ARRAY,
+   .map_name = "func_type_check_btf",
+   .ke

Re: [PATCH bpf-next 00/13] bpf: add btf func info support

2018-10-16 Thread Yonghong Song


On 10/16/18 11:27 AM, Alexei Starovoitov wrote:
> On Fri, Oct 12, 2018 at 11:54:20AM -0700, Yonghong Song wrote:
>> The BTF support was added to kernel by Commit 69b693f0aefa
>> ("bpf: btf: Introduce BPF Type Format (BTF)"), which introduced
>> .BTF section into ELF file and is primarily
>> used for map pretty print.
>> pahole is used to convert dwarf to BTF for ELF files.
>>
>> The next step would be add func type info and debug line info
>> into BTF. For debug line info, it is desirable to encode
>> source code directly in the BTF to ease deployment and
>> introspection.
> 
> it's kinda confusing that cover letter talks about line info next step,
> but these kernel side patches are only for full prog name from btf.
> It certainly makes sense for llvm to do both at the same time.
> Please make the cover letter more clear.

Make sense. Will remove line_info stuff from the cover letter.


Re: [PATCH bpf-next 05/13] bpf: get better bpf_prog ksyms based on btf func type_id

2018-10-16 Thread Yonghong Song


On 10/16/18 10:59 AM, Alexei Starovoitov wrote:
> On Fri, Oct 12, 2018 at 11:54:42AM -0700, Yonghong Song wrote:
>> This patch added interface to load a program with the following
>> additional information:
>> . prog_btf_fd
>> . func_info and func_info_len
>> where func_info will provides function range and type_id
>> corresponding to each function.
>>
>> If verifier agrees with function range provided by the user,
>> the bpf_prog ksym for each function will use the func name
>> provided in the type_id, which is supposed to provide better
>> encoding as it is not limited by 16 bytes program name
>> limitation and this is better for bpf program which contains
>> multiple subprograms.
>>
>> The bpf_prog_info interface is also extended to
>> return btf_id and jited_func_types, so user spaces can
>> print out the function prototype for each jited function.
>>
>> Signed-off-by: Yonghong Song 
> ...
>>  BUILD_BUG_ON(sizeof("bpf_prog_") +
>>   sizeof(prog->tag) * 2 +
>> @@ -401,6 +403,13 @@ static void bpf_get_prog_name(const struct bpf_prog 
>> *prog, char *sym)
>>   
>>  sym += snprintf(sym, KSYM_NAME_LEN, "bpf_prog_");
>>  sym  = bin2hex(sym, prog->tag, sizeof(prog->tag));
>> +
>> +if (prog->aux->btf) {
>> +func_name = btf_get_name_by_id(prog->aux->btf, 
>> prog->aux->type_id);
>> +snprintf(sym, (size_t)(end - sym), "_%s", func_name);
>> +return;
> 
> Would it make sense to add a comment here that prog->aux->name is ignored
> when full btf name is available? (otherwise the same name will appear twice 
> in ksym)

Will add a comment.

> 
>> +}
>> +
>>  if (prog->aux->name[0])
>>  snprintf(sym, (size_t)(end - sym), "_%s", prog->aux->name);
> ...
>> +static int check_btf_func(struct bpf_prog *prog, struct bpf_verifier_env 
>> *env,
>> +  union bpf_attr *attr)
>> +{
>> +struct bpf_func_info *data;
>> +int i, nfuncs, ret = 0;
>> +
>> +if (!attr->func_info_len)
>> +return 0;
>> +
>> +nfuncs = attr->func_info_len / sizeof(struct bpf_func_info);
>> +if (env->subprog_cnt != nfuncs) {
>> +verbose(env, "number of funcs in func_info does not match 
>> verifier\n");
> 
> 'does not match verifier' is hard to make sense of.
> How about 'number of funcs in func_info doesn't match number of subprogs' ?

Sounds good to me.

> 
>> +return -EINVAL;
>> +}
>> +
>> +data = kvmalloc(attr->func_info_len, GFP_KERNEL | __GFP_NOWARN);
>> +if (!data) {
>> +verbose(env, "no memory to allocate attr func_info\n");
> 
> I don't think we ever print such warnings for memory allocations.
> imo this can be removed, since enomem is enough.

Okay.

> 
>> +return -ENOMEM;
>> +}
>> +
>> +if (copy_from_user(data, u64_to_user_ptr(attr->func_info),
>> +   attr->func_info_len)) {
>> +verbose(env, "memory copy error for attr func_info\n");
> 
> similar thing. kernel never warns about copy_from_user errors.

Okay.

> 
>> +ret = -EFAULT;
>> +goto cleanup;
>> +}
>> +
>> +for (i = 0; i < nfuncs; i++) {
>> +if (env->subprog_info[i].start != data[i].insn_offset) {
>> +verbose(env, "func_info subprog start (%d) does not 
>> match verifier (%d)\n",
>> +env->subprog_info[i].start, 
>> data[i].insn_offset);
> 
> I think printing exact insn offset isn't going to be much help
> for regular user to debug it. If this happens, it's likely llvm issue.
> How about 'func_info BTF section doesn't match subprog layout in BPF program' 
> ?

Okay.

> 


Re: [PATCH bpf-next 02/13] bpf: btf: Add BTF_KIND_FUNC and BTF_KIND_FUNC_PROTO

2018-10-16 Thread Yonghong Song


On 10/15/18 3:36 PM, Daniel Borkmann wrote:
> On 10/12/2018 08:54 PM, Yonghong Song wrote:
> [...]
>> +static bool btf_name_valid_identifier(const struct btf *btf, u32 offset)
>> +{
>> +/* offset must be valid */
>> +const char *src = >strings[offset];
>> +
>> +if (!isalpha(*src) && *src != '_')
>> +return false;
>> +
>> +src++;
>> +while (*src) {
>> +if (!isalnum(*src) && *src != '_')
>> +return false;
>> +src++;
>> +}
>> +
>> +return true;
>> +}
> 
> Should there be an upper name length limit like KSYM_NAME_LEN? (Is it implied
> by the kvmalloc() limit?)

KSYM_NAME_LEN is good choice. Here, we check function names and 
struct/union member names. In C, based on
https://stackoverflow.com/questions/2352209/max-identifier-length,
the identifier max length is 63. Some compiler implementation may vary.
KSYM_NAME_LEN is 128.

> 
>>   static const char *btf_name_by_offset(const struct btf *btf, u32 offset)
>>   {
>>  if (!offset)
>> @@ -747,7 +782,9 @@ static bool env_type_is_resolve_sink(const struct 
>> btf_verifier_env *env,
>>  /* int, enum or void is a sink */
>>  return !btf_type_needs_resolve(next_type);
>>  case RESOLVE_PTR:
>> -/* int, enum, void, struct or array is a sink for ptr */
>> +/* int, enum, void, struct, array or func_ptoto is a sink
>> + * for ptr
>> + */
>>  return !btf_type_is_modifier(next_type) &&
>>  !btf_type_is_ptr(next_type);
>>  case RESOLVE_STRUCT_OR_ARRAY:


Re: [PATCH bpf-next 02/13] bpf: btf: Add BTF_KIND_FUNC and BTF_KIND_FUNC_PROTO

2018-10-16 Thread Yonghong Song


On 10/15/18 3:30 PM, Daniel Borkmann wrote:
> On 10/12/2018 08:54 PM, Yonghong Song wrote:
>> This patch adds BTF_KIND_FUNC and BTF_KIND_FUNC_PROTO
>> support to the type section. BTF_KIND_FUNC_PROTO is used
>> to specify the type of a function pointer. With this,
>> BTF has a complete set of C types (except float).
>>
>> BTF_KIND_FUNC is used to specify the signature of a
>> defined subprogram. BTF_KIND_FUNC_PROTO can be referenced
>> by another type, e.g., a pointer type, and BTF_KIND_FUNC
>> type cannot be referenced by another type.
>>
>> For both BTF_KIND_FUNC and BTF_KIND_FUNC_PROTO types,
>> the func return type is in t->type (where t is a
>> "struct btf_type" object). The func args are an array of
>> u32s immediately following object "t".
>>
>> As a concrete example, for the C program below,
>>$ cat test.c
>>int foo(int (*bar)(int)) { return bar(5); }
>> with latest llvm trunk built with Debug mode, we have
>>$ clang -target bpf -g -O2 -mllvm -debug-only=btf -c test.c
>>Type Table:
>>[1] FUNC name_off=1 info=0x0c01 size/type=2
>>param_type=3
>>[2] INT name_off=11 info=0x0100 size/type=4
>>desc=0x0120
>>[3] PTR name_off=0 info=0x0200 size/type=4
>>[4] FUNC_PROTO name_off=0 info=0x0d01 size/type=2
>>param_type=2
>>
>>String Table:
>>0 :
>>1 : foo
>>5 : .text
>>11 : int
>>15 : test.c
>>22 : int foo(int (*bar)(int)) { return bar(5); }
>>
>>FuncInfo Table:
>>sec_name_off=5
>>insn_offset= type_id=1
>>
>>...
>>
>> (Eventually we shall have bpftool to dump btf information
>>   like the above.)
>>
>> Function "foo" has a FUNC type (type_id = 1).
>> The parameter of "foo" has type_id 3 which is PTR->FUNC_PROTO,
>> where FUNC_PROTO refers to function pointer "bar".
> 
> Should also "bar" be part of the string table (at least at some point in 
> future)?

Yes, we can do it. The dwarf for the abovee example looks like

0x0043: DW_TAG_formal_parameter
   DW_AT_location(0x
  [0x,  0x0008): 
DW_OP_reg1 W1
  [0x0008,  0x0018): 
DW_OP_reg2 W2)
   DW_AT_name("bar")
   DW_AT_decl_file   ("/home/yhs/tmp/t.c")
   DW_AT_decl_line   (1)
   DW_AT_type(0x005a "subroutine int*")

0x005a:   DW_TAG_pointer_type
 DW_AT_type  (0x005f "subroutine int")

0x005f:   DW_TAG_subroutine_type
 DW_AT_type  (0x0053 "int")
 DW_AT_prototyped(true)

0x0064: DW_TAG_formal_parameter
   DW_AT_type(0x0053 "int")

0x0069: NULL

0x006a:   NULL

The current llvm implementation does not record func
parameter name, so "bar" got lost. We could associate
"bar" with pointer type in the future implementation.

> Iow, if verifier hints to an issue in the program when it would for example 
> walk
> pointers and rewrite ctx access, then it could dump the var name along with 
> it.
> It might be useful as well in combination with 22 from str table, when 
> annotating
> the source. We might need support for variadic functions, though. How is LLVM
> handling the latter with the recent BTF support?

The LLVM implementation does support variadic functions.
The last type id 0 indicates a variadic function.

> 
>> In FuncInfo Table, for section .text, the function,
>> with to-be-determined offset (marked as ),
>> has type_id=1 which refers to a FUNC type.
>> This way, the function signature is
>> available to both kernel and user space.
>> Here, the insn offset is not available during the dump time
>> as relocation is resolved pretty late in the compilation process.
>>
>> Signed-off-by: Martin KaFai Lau 
>> Signed-off-by: Yonghong Song 


Re: [PATCH bpf-next 05/13] bpf: get better bpf_prog ksyms based on btf func type_id

2018-10-16 Thread Yonghong Song


On 10/15/18 4:12 PM, Martin Lau wrote:
> On Fri, Oct 12, 2018 at 11:54:42AM -0700, Yonghong Song wrote:
>> This patch added interface to load a program with the following
>> additional information:
>> . prog_btf_fd
>> . func_info and func_info_len
>> where func_info will provides function range and type_id
>> corresponding to each function.
>>
>> If verifier agrees with function range provided by the user,
>> the bpf_prog ksym for each function will use the func name
>> provided in the type_id, which is supposed to provide better
>> encoding as it is not limited by 16 bytes program name
>> limitation and this is better for bpf program which contains
>> multiple subprograms.
>>
>> The bpf_prog_info interface is also extended to
>> return btf_id and jited_func_types, so user spaces can
>> print out the function prototype for each jited function.
> Some nits.
> 
>>
>> Signed-off-by: Yonghong Song 
>> ---
>>   include/linux/bpf.h  |  2 +
>>   include/linux/bpf_verifier.h |  1 +
>>   include/linux/btf.h  |  2 +
>>   include/uapi/linux/bpf.h | 11 +
>>   kernel/bpf/btf.c | 16 +++
>>   kernel/bpf/core.c|  9 
>>   kernel/bpf/syscall.c | 86 +++-
>>   kernel/bpf/verifier.c| 50 +
>>   8 files changed, 176 insertions(+), 1 deletion(-)
>>
>> diff --git a/include/linux/bpf.h b/include/linux/bpf.h
>> index 9b558713447f..e9c63ffa01af 100644
>> --- a/include/linux/bpf.h
>> +++ b/include/linux/bpf.h
>> @@ -308,6 +308,8 @@ struct bpf_prog_aux {
>>  void *security;
>>   #endif
>>  struct bpf_prog_offload *offload;
>> +struct btf *btf;
>> +u32 type_id; /* type id for this prog/func */
>>  union {
>>  struct work_struct work;
>>  struct rcu_head rcu;
>> diff --git a/include/linux/bpf_verifier.h b/include/linux/bpf_verifier.h
>> index 9e8056ec20fa..e84782ec50ac 100644
>> --- a/include/linux/bpf_verifier.h
>> +++ b/include/linux/bpf_verifier.h
>> @@ -201,6 +201,7 @@ static inline bool bpf_verifier_log_needed(const struct 
>> bpf_verifier_log *log)
>>   struct bpf_subprog_info {
>>  u32 start; /* insn idx of function entry point */
>>  u16 stack_depth; /* max. stack depth used by this function */
>> +u32 type_id; /* btf type_id for this subprog */
>>   };
>>   
>>   /* single container for all structs
>> diff --git a/include/linux/btf.h b/include/linux/btf.h
>> index e076c4697049..90e91b52aa90 100644
>> --- a/include/linux/btf.h
>> +++ b/include/linux/btf.h
>> @@ -46,5 +46,7 @@ void btf_type_seq_show(const struct btf *btf, u32 type_id, 
>> void *obj,
>> struct seq_file *m);
>>   int btf_get_fd_by_id(u32 id);
>>   u32 btf_id(const struct btf *btf);
>> +bool is_btf_func_type(const struct btf *btf, u32 type_id);
>> +const char *btf_get_name_by_id(const struct btf *btf, u32 type_id);
>>   
>>   #endif
>> diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h
>> index f9187b41dff6..7ebbf4f06a65 100644
>> --- a/include/uapi/linux/bpf.h
>> +++ b/include/uapi/linux/bpf.h
>> @@ -332,6 +332,9 @@ union bpf_attr {
>>   * (context accesses, allowed helpers, etc).
>>   */
>>  __u32   expected_attach_type;
>> +__u32   prog_btf_fd;/* fd pointing to BTF type data 
>> */
>> +__u32   func_info_len;  /* func_info length */
>> +__aligned_u64   func_info;  /* func type info */
>>  };
>>   
>>  struct { /* anonymous struct used by BPF_OBJ_* commands */
>> @@ -2585,6 +2588,9 @@ struct bpf_prog_info {
>>  __u32 nr_jited_func_lens;
>>  __aligned_u64 jited_ksyms;
>>  __aligned_u64 jited_func_lens;
>> +__u32 btf_id;
>> +__u32 nr_jited_func_types;
>> +__aligned_u64 jited_func_types;
>>   } __attribute__((aligned(8)));
>>   
>>   struct bpf_map_info {
>> @@ -2896,4 +2902,9 @@ struct bpf_flow_keys {
>>  };
>>   };
>>   
>> +struct bpf_func_info {
>> +__u32   insn_offset;
>> +__u32   type_id;
>> +};
>> +
>>   #endif /* _UAPI__LINUX_BPF_H__ */
>> diff --git a/kernel/bpf/btf.c b/kernel/bpf/btf.c
>> index 794a185f11bf..85b8eeccddbd 100644
>> --- a/kernel/bpf/btf.c
>> +++ b/kernel/bpf/btf.c
>> @@ -486,6 +486,15 @@ static const struct btf_type *btf_typ

[PATCH bpf-next 11/13] tools/bpf: refactor to implement btf_get_from_id() in lib/bpf

2018-10-12 Thread Yonghong Song
The function get_btf() is implemented in tools/bpf/bpftool/map.c
to get a btf structure given a map_info. This patch
refactored this function to be function btf_get_from_id()
in tools/lib/bpf so that it can be used later.

Signed-off-by: Yonghong Song 
---
 tools/bpf/bpftool/map.c | 68 ++--
 tools/lib/bpf/btf.c | 69 +
 tools/lib/bpf/btf.h |  1 +
 3 files changed, 72 insertions(+), 66 deletions(-)

diff --git a/tools/bpf/bpftool/map.c b/tools/bpf/bpftool/map.c
index 9f5de48f8a99..33c7dc8ddd86 100644
--- a/tools/bpf/bpftool/map.c
+++ b/tools/bpf/bpftool/map.c
@@ -203,70 +203,6 @@ static int do_dump_btf(const struct btf_dumper *d,
return ret;
 }
 
-static int get_btf(struct bpf_map_info *map_info, struct btf **btf)
-{
-   struct bpf_btf_info btf_info = { 0 };
-   __u32 len = sizeof(btf_info);
-   __u32 last_size;
-   int btf_fd;
-   void *ptr;
-   int err;
-
-   err = 0;
-   *btf = NULL;
-   btf_fd = bpf_btf_get_fd_by_id(map_info->btf_id);
-   if (btf_fd < 0)
-   return 0;
-
-   /* we won't know btf_size until we call bpf_obj_get_info_by_fd(). so
-* let's start with a sane default - 4KiB here - and resize it only if
-* bpf_obj_get_info_by_fd() needs a bigger buffer.
-*/
-   btf_info.btf_size = 4096;
-   last_size = btf_info.btf_size;
-   ptr = malloc(last_size);
-   if (!ptr) {
-   err = -ENOMEM;
-   goto exit_free;
-   }
-
-   bzero(ptr, last_size);
-   btf_info.btf = ptr_to_u64(ptr);
-   err = bpf_obj_get_info_by_fd(btf_fd, _info, );
-
-   if (!err && btf_info.btf_size > last_size) {
-   void *temp_ptr;
-
-   last_size = btf_info.btf_size;
-   temp_ptr = realloc(ptr, last_size);
-   if (!temp_ptr) {
-   err = -ENOMEM;
-   goto exit_free;
-   }
-   ptr = temp_ptr;
-   bzero(ptr, last_size);
-   btf_info.btf = ptr_to_u64(ptr);
-   err = bpf_obj_get_info_by_fd(btf_fd, _info, );
-   }
-
-   if (err || btf_info.btf_size > last_size) {
-   err = errno;
-   goto exit_free;
-   }
-
-   *btf = btf__new((__u8 *)btf_info.btf, btf_info.btf_size, NULL);
-   if (IS_ERR(*btf)) {
-   err = PTR_ERR(*btf);
-   *btf = NULL;
-   }
-
-exit_free:
-   close(btf_fd);
-   free(ptr);
-
-   return err;
-}
-
 static json_writer_t *get_btf_writer(void)
 {
json_writer_t *jw = jsonw_new(stdout);
@@ -753,7 +689,7 @@ static int do_dump(int argc, char **argv)
 
prev_key = NULL;
 
-   err = get_btf(, );
+   err = btf_get_from_id(info.btf_id, );
if (err) {
p_err("failed to get btf");
goto exit_free;
@@ -897,7 +833,7 @@ static int do_lookup(int argc, char **argv)
}
 
/* here means bpf_map_lookup_elem() succeeded */
-   err = get_btf(, );
+   err = btf_get_from_id(info.btf_id, );
if (err) {
p_err("failed to get btf");
goto exit_free;
diff --git a/tools/lib/bpf/btf.c b/tools/lib/bpf/btf.c
index 4748e0bacd2b..ab654628e966 100644
--- a/tools/lib/bpf/btf.c
+++ b/tools/lib/bpf/btf.c
@@ -42,6 +42,11 @@ struct btf_ext {
__u32 func_info_len;
 };
 
+static inline __u64 ptr_to_u64(const void *ptr)
+{
+   return (__u64) (unsigned long) ptr;
+}
+
 static int btf_add_type(struct btf *btf, struct btf_type *t)
 {
if (btf->types_size - btf->nr_types < 2) {
@@ -403,6 +408,70 @@ const char *btf__name_by_offset(const struct btf *btf, 
__u32 offset)
return NULL;
 }
 
+int btf_get_from_id(__u32 id, struct btf **btf)
+{
+   struct bpf_btf_info btf_info = { 0 };
+   __u32 len = sizeof(btf_info);
+   __u32 last_size;
+   int btf_fd;
+   void *ptr;
+   int err;
+
+   err = 0;
+   *btf = NULL;
+   btf_fd = bpf_btf_get_fd_by_id(id);
+   if (btf_fd < 0)
+   return 0;
+
+   /* we won't know btf_size until we call bpf_obj_get_info_by_fd(). so
+* let's start with a sane default - 4KiB here - and resize it only if
+* bpf_obj_get_info_by_fd() needs a bigger buffer.
+*/
+   btf_info.btf_size = 4096;
+   last_size = btf_info.btf_size;
+   ptr = malloc(last_size);
+   if (!ptr) {
+   err = -ENOMEM;
+   goto exit_free;
+   }
+
+   bzero(ptr, last_size);
+   btf_info.btf = ptr_to_u64(ptr);
+   err = bpf_obj_get_info_by_fd(btf_fd, _info, );
+
+   if (!err && btf_info.btf_size > last_size) {
+   void *temp_ptr;
+
+   last_size = btf_info.btf_size;
+   temp_ptr = realloc(ptr, last_size);
+   if (!temp_ptr) {
+   

[PATCH bpf-next 12/13] tools/bpf: enhance test_btf file testing to test func info

2018-10-12 Thread Yonghong Song
Change the bpf programs test_btf_haskv.c and test_btf_nokv.c to
have two sections, and enhance test_btf.c test_file feature
to test btf func_info returned by the kernel.

Signed-off-by: Yonghong Song 
---
 tools/testing/selftests/bpf/test_btf.c   | 72 +++-
 tools/testing/selftests/bpf/test_btf_haskv.c | 16 -
 tools/testing/selftests/bpf/test_btf_nokv.c  | 16 -
 3 files changed, 99 insertions(+), 5 deletions(-)

diff --git a/tools/testing/selftests/bpf/test_btf.c 
b/tools/testing/selftests/bpf/test_btf.c
index e03a8cea4bb7..0bbefb571426 100644
--- a/tools/testing/selftests/bpf/test_btf.c
+++ b/tools/testing/selftests/bpf/test_btf.c
@@ -2235,10 +2235,16 @@ static int file_has_btf_elf(const char *fn)
 static int do_test_file(unsigned int test_num)
 {
const struct btf_file_test *test = _tests[test_num - 1];
+   const char *expected_fnames[] = {"_dummy_tracepoint",
+"test_long_fname_1",
+"test_long_fname_2"};
+   __u32 func_lens[10], func_types[10], info_len;
+   struct bpf_prog_info info = {};
struct bpf_object *obj = NULL;
struct bpf_program *prog;
+   struct btf *btf = NULL;
struct bpf_map *map;
-   int err;
+   int i, err, prog_fd;
 
fprintf(stderr, "BTF libbpf test[%u] (%s): ", test_num,
test->file);
@@ -2271,6 +2277,7 @@ static int do_test_file(unsigned int test_num)
err = bpf_object__load(obj);
if (CHECK(err < 0, "bpf_object__load: %d", err))
goto done;
+   prog_fd = bpf_program__fd(prog);
 
map = bpf_object__find_map_by_name(obj, "btf_map");
if (CHECK(!map, "btf_map not found")) {
@@ -2285,6 +2292,69 @@ static int do_test_file(unsigned int test_num)
  test->btf_kv_notfound))
goto done;
 
+   if (!jit_enabled)
+   goto skip_jit;
+
+   info_len = sizeof(struct bpf_prog_info);
+   info.nr_jited_func_types = ARRAY_SIZE(func_types);
+   info.nr_jited_func_lens = ARRAY_SIZE(func_lens);
+   info.jited_func_types = ptr_to_u64(_types[0]);
+   info.jited_func_lens = ptr_to_u64(_lens[0]);
+
+   err = bpf_obj_get_info_by_fd(prog_fd, , _len);
+
+   if (CHECK(err == -1, "invalid get info errno:%d", errno)) {
+   fprintf(stderr, "%s\n", btf_log_buf);
+   err = -1;
+   goto done;
+   }
+   if (CHECK(info.nr_jited_func_lens != 3,
+ "incorrect info.nr_jited_func_lens %d",
+ info.nr_jited_func_lens)) {
+   err = -1;
+   goto done;
+   }
+   if (CHECK(info.nr_jited_func_types != 3,
+ "incorrect info.nr_jited_func_types %d",
+ info.nr_jited_func_types)) {
+   err = -1;
+   goto done;
+   }
+   if (CHECK(info.btf_id == 0, "incorrect btf_id = 0")) {
+   err = -1;
+   goto done;
+   }
+
+   err = btf_get_from_id(info.btf_id, );
+   if (CHECK(err, "cannot get btf from kernel, err: %d", err))
+   goto done;
+
+   /* check three functions */
+   for (i = 0; i < 3; i++) {
+   const struct btf_type *t;
+   const char *fname;
+
+   t = btf__type_by_id(btf, func_types[i]);
+   if (CHECK(!t, "btf__type_by_id failure: id %u",
+ func_types[i])) {
+   err = -1;
+   goto done;
+   }
+
+   fname = btf__name_by_offset(btf, t->name_off);
+   err = strcmp(fname, expected_fnames[i]);
+   /* for the second and third functions in .text section,
+* the compiler may order them either way.
+*/
+   if (i && err)
+   err = strcmp(fname, expected_fnames[3 - i]);
+   if (CHECK(err, "incorrect fname %s", fname ? : "")) {
+   err = -1;
+   goto done;
+   }
+   }
+
+skip_jit:
fprintf(stderr, "OK");
 
 done:
diff --git a/tools/testing/selftests/bpf/test_btf_haskv.c 
b/tools/testing/selftests/bpf/test_btf_haskv.c
index b21b876f475d..e5c79fe0ffdb 100644
--- a/tools/testing/selftests/bpf/test_btf_haskv.c
+++ b/tools/testing/selftests/bpf/test_btf_haskv.c
@@ -24,8 +24,8 @@ struct dummy_tracepoint_args {
struct sock *sock;
 };
 
-SEC("dummy_tracepoint")
-int _dummy_tracepoint(struct dummy_tracepoint_args *arg)
+__attribute__((noinline))
+static int test_long_fname_2(struct dummy_tracepoint_args *arg)
 {
struct ipv_counts *counts;
int key = 0;
@@ -42,4 +42,16 @@ int _dummy_tracepoint(struct dummy_tracepoint

[PATCH bpf-next 13/13] tools/bpf: bpftool: add support for jited func types

2018-10-12 Thread Yonghong Song
This patch added support to print function signature
if btf func_info is available. Note that ksym
now uses function name instead of prog_name as
prog_name has a limit of 16 bytes including
ending '\0'.

The following is a sample output for selftests
test_btf with file test_btf_haskv.o:

  $ bpftool prog dump jited id 1
  int _dummy_tracepoint(struct dummy_tracepoint_args * ):
  bpf_prog_b07ccb89267cf242__dummy_tracepoint:
 0:   push   %rbp
 1:   mov%rsp,%rbp
..
3c:   add$0x28,%rbp
40:   leaveq
41:   retq

  int test_long_fname_1(struct dummy_tracepoint_args * ):
  bpf_prog_2dcecc18072623fc_test_long_fname_1:
 0:   push   %rbp
 1:   mov%rsp,%rbp
..
3a:   add$0x28,%rbp
3e:   leaveq
3f:   retq

  int test_long_fname_2(struct dummy_tracepoint_args * ):
  bpf_prog_89d64e4abf0f0126_test_long_fname_2:
 0:   push   %rbp
 1:   mov%rsp,%rbp
..
80:   add$0x28,%rbp
84:   leaveq
85:   retq

Signed-off-by: Yonghong Song 
---
 tools/bpf/bpftool/btf_dumper.c | 96 ++
 tools/bpf/bpftool/main.h   |  2 +
 tools/bpf/bpftool/prog.c   | 54 +++
 3 files changed, 152 insertions(+)

diff --git a/tools/bpf/bpftool/btf_dumper.c b/tools/bpf/bpftool/btf_dumper.c
index 55bc512a1831..a31df4202335 100644
--- a/tools/bpf/bpftool/btf_dumper.c
+++ b/tools/bpf/bpftool/btf_dumper.c
@@ -249,3 +249,99 @@ int btf_dumper_type(const struct btf_dumper *d, __u32 
type_id,
 {
return btf_dumper_do_type(d, type_id, 0, data);
 }
+
+#define BTF_PRINT_STRING(str)  \
+   {   \
+   pos += snprintf(func_sig + pos, size - pos, str);   \
+   if (pos >= size)\
+   return -1;  \
+   }
+#define BTF_PRINT_ONE_ARG(fmt, arg)\
+   {   \
+   pos += snprintf(func_sig + pos, size - pos, fmt, arg);  \
+   if (pos >= size)\
+   return -1;  \
+   }
+#define BTF_PRINT_TYPE_ONLY(type)  \
+   {   \
+   pos = __btf_dumper_type_only(btf, type, func_sig,   \
+pos, size);\
+   if (pos == -1)  \
+   return -1;  \
+   }
+
+static int __btf_dumper_type_only(struct btf *btf, __u32 type_id,
+ char *func_sig, int pos, int size)
+{
+   const struct btf_type *t = btf__type_by_id(btf, type_id);
+   const struct btf_array *array;
+   int i, vlen;
+
+   switch (BTF_INFO_KIND(t->info)) {
+   case BTF_KIND_INT:
+   BTF_PRINT_ONE_ARG("%s ",
+ btf__name_by_offset(btf, t->name_off));
+   break;
+   case BTF_KIND_STRUCT:
+   BTF_PRINT_ONE_ARG("struct %s ",
+ btf__name_by_offset(btf, t->name_off));
+   break;
+   case BTF_KIND_UNION:
+   BTF_PRINT_ONE_ARG("union %s ",
+ btf__name_by_offset(btf, t->name_off));
+   break;
+   case BTF_KIND_ENUM:
+   BTF_PRINT_ONE_ARG("enum %s ",
+ btf__name_by_offset(btf, t->name_off));
+   break;
+   case BTF_KIND_ARRAY:
+   array = (struct btf_array *)(t + 1);
+   BTF_PRINT_TYPE_ONLY(array->type);
+   BTF_PRINT_ONE_ARG("[%d]", array->nelems);
+   break;
+   case BTF_KIND_PTR:
+   BTF_PRINT_TYPE_ONLY(t->type);
+   BTF_PRINT_STRING("* ");
+   break;
+   case BTF_KIND_UNKN:
+   case BTF_KIND_FWD:
+   case BTF_KIND_TYPEDEF:
+   return -1;
+   case BTF_KIND_VOLATILE:
+   BTF_PRINT_STRING("volatile ");
+   BTF_PRINT_TYPE_ONLY(t->type);
+   break;
+   case BTF_KIND_CONST:
+   BTF_PRINT_STRING("const ");
+   BTF_PRINT_TYPE_ONLY(t->type);
+   break;
+   case BTF_KIND_RESTRICT:
+   BTF_PRINT_STRING("restrict ");
+   BTF_PRINT_TYPE_ONLY(t->type);
+   break;
+   case BTF_KIND_FUNC:
+   case BTF_KIND_FUNC_PROTO:
+   BTF_PRINT_TYPE_ONLY(t->type);
+   BTF_PRINT_ONE_ARG("%s(", btf__name_by_offset

[PATCH bpf-next 10/13] tools/bpf: do not use pahole if clang/llvm can generate BTF sections

2018-10-12 Thread Yonghong Song
Add additional checks in tools/testing/selftests/bpf and
samples/bpf such that if clang/llvm compiler can generate
BTF sections, do not use pahole.

Signed-off-by: Yonghong Song 
---
 samples/bpf/Makefile | 8 
 tools/testing/selftests/bpf/Makefile | 8 
 2 files changed, 16 insertions(+)

diff --git a/samples/bpf/Makefile b/samples/bpf/Makefile
index be0a961450bc..870fe7ee2b69 100644
--- a/samples/bpf/Makefile
+++ b/samples/bpf/Makefile
@@ -208,12 +208,20 @@ endif
 BTF_LLC_PROBE := $(shell $(LLC) -march=bpf -mattr=help 2>&1 | grep dwarfris)
 BTF_PAHOLE_PROBE := $(shell $(BTF_PAHOLE) --help 2>&1 | grep BTF)
 BTF_OBJCOPY_PROBE := $(shell $(LLVM_OBJCOPY) --help 2>&1 | grep -i 
'usage.*llvm')
+BTF_LLVM_PROBE := $(shell echo "int main() { return 0; }" | \
+ clang -target bpf -O2 -g -c -x c - -o 
./llvm_btf_verify.o; \
+ readelf -S ./llvm_btf_verify.o | grep BTF; \
+ /bin/rm -f ./llvm_btf_verify.o)
 
+ifneq ($(BTF_LLVM_PROBE),)
+   EXTRA_CFLAGS += -g
+else
 ifneq ($(and $(BTF_LLC_PROBE),$(BTF_PAHOLE_PROBE),$(BTF_OBJCOPY_PROBE)),)
EXTRA_CFLAGS += -g
LLC_FLAGS += -mattr=dwarfris
DWARF2BTF = y
 endif
+endif
 
 # Trick to allow make to be run from this directory
 all:
diff --git a/tools/testing/selftests/bpf/Makefile 
b/tools/testing/selftests/bpf/Makefile
index d24afe8b821d..83240e54c6a8 100644
--- a/tools/testing/selftests/bpf/Makefile
+++ b/tools/testing/selftests/bpf/Makefile
@@ -119,7 +119,14 @@ $(OUTPUT)/test_xdp_noinline.o: CLANG_FLAGS += -fno-inline
 BTF_LLC_PROBE := $(shell $(LLC) -march=bpf -mattr=help 2>&1 | grep dwarfris)
 BTF_PAHOLE_PROBE := $(shell $(BTF_PAHOLE) --help 2>&1 | grep BTF)
 BTF_OBJCOPY_PROBE := $(shell $(LLVM_OBJCOPY) --help 2>&1 | grep -i 
'usage.*llvm')
+BTF_LLVM_PROBE := $(shell echo "int main() { return 0; }" | \
+ clang -target bpf -O2 -g -c -x c - -o 
./llvm_btf_verify.o; \
+ readelf -S ./llvm_btf_verify.o | grep BTF; \
+ /bin/rm -f ./llvm_btf_verify.o)
 
+ifneq ($(BTF_LLVM_PROBE),)
+   CLANG_FLAGS += -g
+else
 ifneq ($(BTF_LLC_PROBE),)
 ifneq ($(BTF_PAHOLE_PROBE),)
 ifneq ($(BTF_OBJCOPY_PROBE),)
@@ -129,6 +136,7 @@ ifneq ($(BTF_OBJCOPY_PROBE),)
 endif
 endif
 endif
+endif
 
 $(OUTPUT)/%.o: %.c
$(CLANG) $(CLANG_FLAGS) \
-- 
2.17.1



[PATCH bpf-next 05/13] bpf: get better bpf_prog ksyms based on btf func type_id

2018-10-12 Thread Yonghong Song
This patch added interface to load a program with the following
additional information:
   . prog_btf_fd
   . func_info and func_info_len
where func_info will provides function range and type_id
corresponding to each function.

If verifier agrees with function range provided by the user,
the bpf_prog ksym for each function will use the func name
provided in the type_id, which is supposed to provide better
encoding as it is not limited by 16 bytes program name
limitation and this is better for bpf program which contains
multiple subprograms.

The bpf_prog_info interface is also extended to
return btf_id and jited_func_types, so user spaces can
print out the function prototype for each jited function.

Signed-off-by: Yonghong Song 
---
 include/linux/bpf.h  |  2 +
 include/linux/bpf_verifier.h |  1 +
 include/linux/btf.h  |  2 +
 include/uapi/linux/bpf.h | 11 +
 kernel/bpf/btf.c | 16 +++
 kernel/bpf/core.c|  9 
 kernel/bpf/syscall.c | 86 +++-
 kernel/bpf/verifier.c| 50 +
 8 files changed, 176 insertions(+), 1 deletion(-)

diff --git a/include/linux/bpf.h b/include/linux/bpf.h
index 9b558713447f..e9c63ffa01af 100644
--- a/include/linux/bpf.h
+++ b/include/linux/bpf.h
@@ -308,6 +308,8 @@ struct bpf_prog_aux {
void *security;
 #endif
struct bpf_prog_offload *offload;
+   struct btf *btf;
+   u32 type_id; /* type id for this prog/func */
union {
struct work_struct work;
struct rcu_head rcu;
diff --git a/include/linux/bpf_verifier.h b/include/linux/bpf_verifier.h
index 9e8056ec20fa..e84782ec50ac 100644
--- a/include/linux/bpf_verifier.h
+++ b/include/linux/bpf_verifier.h
@@ -201,6 +201,7 @@ static inline bool bpf_verifier_log_needed(const struct 
bpf_verifier_log *log)
 struct bpf_subprog_info {
u32 start; /* insn idx of function entry point */
u16 stack_depth; /* max. stack depth used by this function */
+   u32 type_id; /* btf type_id for this subprog */
 };
 
 /* single container for all structs
diff --git a/include/linux/btf.h b/include/linux/btf.h
index e076c4697049..90e91b52aa90 100644
--- a/include/linux/btf.h
+++ b/include/linux/btf.h
@@ -46,5 +46,7 @@ void btf_type_seq_show(const struct btf *btf, u32 type_id, 
void *obj,
   struct seq_file *m);
 int btf_get_fd_by_id(u32 id);
 u32 btf_id(const struct btf *btf);
+bool is_btf_func_type(const struct btf *btf, u32 type_id);
+const char *btf_get_name_by_id(const struct btf *btf, u32 type_id);
 
 #endif
diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h
index f9187b41dff6..7ebbf4f06a65 100644
--- a/include/uapi/linux/bpf.h
+++ b/include/uapi/linux/bpf.h
@@ -332,6 +332,9 @@ union bpf_attr {
 * (context accesses, allowed helpers, etc).
 */
__u32   expected_attach_type;
+   __u32   prog_btf_fd;/* fd pointing to BTF type data 
*/
+   __u32   func_info_len;  /* func_info length */
+   __aligned_u64   func_info;  /* func type info */
};
 
struct { /* anonymous struct used by BPF_OBJ_* commands */
@@ -2585,6 +2588,9 @@ struct bpf_prog_info {
__u32 nr_jited_func_lens;
__aligned_u64 jited_ksyms;
__aligned_u64 jited_func_lens;
+   __u32 btf_id;
+   __u32 nr_jited_func_types;
+   __aligned_u64 jited_func_types;
 } __attribute__((aligned(8)));
 
 struct bpf_map_info {
@@ -2896,4 +2902,9 @@ struct bpf_flow_keys {
};
 };
 
+struct bpf_func_info {
+   __u32   insn_offset;
+   __u32   type_id;
+};
+
 #endif /* _UAPI__LINUX_BPF_H__ */
diff --git a/kernel/bpf/btf.c b/kernel/bpf/btf.c
index 794a185f11bf..85b8eeccddbd 100644
--- a/kernel/bpf/btf.c
+++ b/kernel/bpf/btf.c
@@ -486,6 +486,15 @@ static const struct btf_type *btf_type_by_id(const struct 
btf *btf, u32 type_id)
return btf->types[type_id];
 }
 
+bool is_btf_func_type(const struct btf *btf, u32 type_id)
+{
+   const struct btf_type *type = btf_type_by_id(btf, type_id);
+
+   if (!type || BTF_INFO_KIND(type->info) != BTF_KIND_FUNC)
+   return false;
+   return true;
+}
+
 /*
  * Regular int is not a bit field and it must be either
  * u8/u16/u32/u64.
@@ -2579,3 +2588,10 @@ u32 btf_id(const struct btf *btf)
 {
return btf->id;
 }
+
+const char *btf_get_name_by_id(const struct btf *btf, u32 type_id)
+{
+   const struct btf_type *t = btf_type_by_id(btf, type_id);
+
+   return btf_name_by_offset(btf, t->name_off);
+}
diff --git a/kernel/bpf/core.c b/kernel/bpf/core.c
index 3f5bf1af0826..add3866a120e 100644
--- a/kernel/bpf/core.c
+++ b/kernel/bpf/core.c
@@ -27,6 +27,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -387,6 +388,7 @@ bpf_get_prog_addr_region(const struct bpf_prog *prog,
 static void bpf_get_prog_name(

[PATCH bpf-next 06/13] tools/bpf: sync kernel uapi bpf.h header to tools directory

2018-10-12 Thread Yonghong Song
The kernel uapi bpf.h is synced to tools directory.

Signed-off-by: Yonghong Song 
---
 tools/include/uapi/linux/bpf.h | 11 +++
 1 file changed, 11 insertions(+)

diff --git a/tools/include/uapi/linux/bpf.h b/tools/include/uapi/linux/bpf.h
index f9187b41dff6..7ebbf4f06a65 100644
--- a/tools/include/uapi/linux/bpf.h
+++ b/tools/include/uapi/linux/bpf.h
@@ -332,6 +332,9 @@ union bpf_attr {
 * (context accesses, allowed helpers, etc).
 */
__u32   expected_attach_type;
+   __u32   prog_btf_fd;/* fd pointing to BTF type data 
*/
+   __u32   func_info_len;  /* func_info length */
+   __aligned_u64   func_info;  /* func type info */
};
 
struct { /* anonymous struct used by BPF_OBJ_* commands */
@@ -2585,6 +2588,9 @@ struct bpf_prog_info {
__u32 nr_jited_func_lens;
__aligned_u64 jited_ksyms;
__aligned_u64 jited_func_lens;
+   __u32 btf_id;
+   __u32 nr_jited_func_types;
+   __aligned_u64 jited_func_types;
 } __attribute__((aligned(8)));
 
 struct bpf_map_info {
@@ -2896,4 +2902,9 @@ struct bpf_flow_keys {
};
 };
 
+struct bpf_func_info {
+   __u32   insn_offset;
+   __u32   type_id;
+};
+
 #endif /* _UAPI__LINUX_BPF_H__ */
-- 
2.17.1



[PATCH bpf-next 07/13] tools/bpf: add new fields for program load in lib/bpf

2018-10-12 Thread Yonghong Song
The new fields are added for program load in lib/bpf so
application uses api bpf_load_program_xattr() is able
to load program with btf and func_info data.

This functionality will be used in next patch
by bpf selftest test_btf.

Signed-off-by: Yonghong Song 
---
 tools/lib/bpf/bpf.c | 3 +++
 tools/lib/bpf/bpf.h | 3 +++
 2 files changed, 6 insertions(+)

diff --git a/tools/lib/bpf/bpf.c b/tools/lib/bpf/bpf.c
index d70a255cb05e..d8d48ab34220 100644
--- a/tools/lib/bpf/bpf.c
+++ b/tools/lib/bpf/bpf.c
@@ -196,6 +196,9 @@ int bpf_load_program_xattr(const struct 
bpf_load_program_attr *load_attr,
attr.log_level = 0;
attr.kern_version = load_attr->kern_version;
attr.prog_ifindex = load_attr->prog_ifindex;
+   attr.prog_btf_fd = load_attr->prog_btf_fd;
+   attr.func_info_len = load_attr->func_info_len;
+   attr.func_info = ptr_to_u64(load_attr->func_info);
memcpy(attr.prog_name, load_attr->name,
   min(name_len, BPF_OBJ_NAME_LEN - 1));
 
diff --git a/tools/lib/bpf/bpf.h b/tools/lib/bpf/bpf.h
index 87520a87a75f..d8fe72b22168 100644
--- a/tools/lib/bpf/bpf.h
+++ b/tools/lib/bpf/bpf.h
@@ -67,6 +67,9 @@ struct bpf_load_program_attr {
const char *license;
__u32 kern_version;
__u32 prog_ifindex;
+   __u32 prog_btf_fd;
+   __u32 func_info_len;
+   const struct bpf_func_info *func_info;
 };
 
 /* Recommend log buffer size */
-- 
2.17.1



[PATCH bpf-next 03/13] tools/bpf: sync kernel btf.h header

2018-10-12 Thread Yonghong Song
The kernel uapi btf.h is synced to the tools directory.

Signed-off-by: Martin KaFai Lau 
Signed-off-by: Yonghong Song 
---
 tools/include/uapi/linux/btf.h | 9 ++---
 1 file changed, 6 insertions(+), 3 deletions(-)

diff --git a/tools/include/uapi/linux/btf.h b/tools/include/uapi/linux/btf.h
index 972265f32871..63f8500e6f34 100644
--- a/tools/include/uapi/linux/btf.h
+++ b/tools/include/uapi/linux/btf.h
@@ -40,7 +40,8 @@ struct btf_type {
/* "size" is used by INT, ENUM, STRUCT and UNION.
 * "size" tells the size of the type it is describing.
 *
-* "type" is used by PTR, TYPEDEF, VOLATILE, CONST and RESTRICT.
+* "type" is used by PTR, TYPEDEF, VOLATILE, CONST, RESTRICT,
+* FUNC and FUNC_PROTO.
 * "type" is a type_id referring to another type.
 */
union {
@@ -64,8 +65,10 @@ struct btf_type {
 #define BTF_KIND_VOLATILE  9   /* Volatile */
 #define BTF_KIND_CONST 10  /* Const*/
 #define BTF_KIND_RESTRICT  11  /* Restrict */
-#define BTF_KIND_MAX   11
-#define NR_BTF_KINDS   12
+#define BTF_KIND_FUNC  12  /* Function */
+#define BTF_KIND_FUNC_PROTO13  /* Function Prototype   */
+#define BTF_KIND_MAX   13
+#define NR_BTF_KINDS   14
 
 /* For some specific BTF_KIND, "struct btf_type" is immediately
  * followed by extra data.
-- 
2.17.1



[PATCH bpf-next 08/13] tools/bpf: extends test_btf to test load/retrieve func_type info

2018-10-12 Thread Yonghong Song
A two function bpf program is loaded with btf and func_info.
After successful prog load, the bpf_get_info syscall is called
to retrieve prog info to ensure the types returned from the
kernel matches the types passed to the kernel from the
user space.

Several negative tests are also added to test loading/retriving
of func_type info.

Signed-off-by: Yonghong Song 
---
 tools/testing/selftests/bpf/test_btf.c | 278 -
 1 file changed, 275 insertions(+), 3 deletions(-)

diff --git a/tools/testing/selftests/bpf/test_btf.c 
b/tools/testing/selftests/bpf/test_btf.c
index b6461c3c5e11..e03a8cea4bb7 100644
--- a/tools/testing/selftests/bpf/test_btf.c
+++ b/tools/testing/selftests/bpf/test_btf.c
@@ -5,6 +5,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -22,9 +23,13 @@
 #include "bpf_rlimit.h"
 #include "bpf_util.h"
 
+#define MAX_INSNS  512
+#define MAX_SUBPROGS   16
+
 static uint32_t pass_cnt;
 static uint32_t error_cnt;
 static uint32_t skip_cnt;
+static bool jit_enabled;
 
 #define CHECK(condition, format...) ({ \
int __ret = !!(condition);  \
@@ -60,6 +65,24 @@ static int __base_pr(const char *format, ...)
return err;
 }
 
+static bool is_jit_enabled(void)
+{
+   const char *jit_sysctl = "/proc/sys/net/core/bpf_jit_enable";
+   bool enabled = false;
+   int sysctl_fd;
+
+   sysctl_fd = open(jit_sysctl, 0, O_RDONLY);
+   if (sysctl_fd != -1) {
+   char tmpc;
+
+   if (read(sysctl_fd, , sizeof(tmpc)) == 1)
+   enabled = (tmpc != '0');
+   close(sysctl_fd);
+   }
+
+   return enabled;
+}
+
 #define BTF_INFO_ENC(kind, root, vlen) \
((!!(root) << 31) | ((kind) << 24) | ((vlen) & BTF_MAX_VLEN))
 
@@ -103,6 +126,7 @@ static struct args {
bool get_info_test;
bool pprint_test;
bool always_log;
+   bool func_type_test;
 } args;
 
 static char btf_log_buf[BTF_LOG_BUF_SIZE];
@@ -2693,16 +2717,256 @@ static int test_pprint(void)
return err;
 }
 
+static struct btf_func_type_test {
+   const char *descr;
+   const char *str_sec;
+   __u32 raw_types[MAX_NR_RAW_TYPES];
+   __u32 str_sec_size;
+   struct bpf_insn insns[MAX_INSNS];
+   __u32 prog_type;
+   struct bpf_func_info func_info[MAX_SUBPROGS];
+   __u32 func_info_len;
+   bool expected_prog_load_failure;
+} func_type_test[] = {
+
+{
+   .descr = "func_type test #1",
+   .str_sec = "\0int\0unsigned int\0funcA\0funcB",
+   .raw_types = {
+   BTF_TYPE_INT_ENC(NAME_TBD, BTF_INT_SIGNED, 0, 32, 4),  /* [1] */
+   BTF_TYPE_INT_ENC(NAME_TBD, 0, 0, 32, 4),   /* [2] */
+   BTF_TYPE_ENC(NAME_TBD, BTF_INFO_ENC(BTF_KIND_FUNC, 0, 2), 1),  
/* [3] */
+   1, 2,
+   BTF_TYPE_ENC(NAME_TBD, BTF_INFO_ENC(BTF_KIND_FUNC, 0, 2), 1),  
/* [4] */
+   2, 1,
+   BTF_END_RAW,
+   },
+   .str_sec_size = sizeof("\0int\0unsigned int\0funcA\0funcB"),
+   .insns = {
+   BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 1, 0, 2),
+   BPF_MOV64_IMM(BPF_REG_0, 1),
+   BPF_EXIT_INSN(),
+   BPF_MOV64_IMM(BPF_REG_0, 2),
+   BPF_EXIT_INSN(),
+   },
+   .prog_type = BPF_PROG_TYPE_TRACEPOINT,
+   .func_info = { {0, 3}, {3, 4} },
+   .func_info_len = 2 * sizeof(struct bpf_func_info),
+},
+
+{
+   .descr = "func_type test #2",
+   .str_sec = "\0int\0unsigned int\0funcA\0funcB",
+   .raw_types = {
+   BTF_TYPE_INT_ENC(NAME_TBD, BTF_INT_SIGNED, 0, 32, 4),  /* [1] */
+   BTF_TYPE_INT_ENC(NAME_TBD, 0, 0, 32, 4),   /* [2] */
+   /* incorrect func type */
+   BTF_TYPE_ENC(NAME_TBD, BTF_INFO_ENC(BTF_KIND_FUNC_PROTO, 0, 2), 
1),  /* [3] */
+   1, 2,
+   BTF_TYPE_ENC(NAME_TBD, BTF_INFO_ENC(BTF_KIND_FUNC, 0, 2), 1),  
/* [4] */
+   2, 1,
+   BTF_END_RAW,
+   },
+   .str_sec_size = sizeof("\0int\0unsigned int\0funcA\0funcB"),
+   .insns = {
+   BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 1, 0, 2),
+   BPF_MOV64_IMM(BPF_REG_0, 1),
+   BPF_EXIT_INSN(),
+   BPF_MOV64_IMM(BPF_REG_0, 2),
+   BPF_EXIT_INSN(),
+   },
+   .prog_type = BPF_PROG_TYPE_TRACEPOINT,
+   .func_info = { {0, 3}, {3, 4} },
+   .func_info_len = 2 * sizeof(struct bpf_func_info),
+   .expected_prog_load_failure = true,
+},
+
+{
+   .descr = "func_type test #3",
+   .str_sec = "\0int\0unsigned int\0funcA\0funcB",
+   .raw_types = {
+   BTF_TYPE_INT_ENC(NAME_TBD, BTF_INT_SIGNED, 0, 32, 4),  /* [1] */
+ 

[PATCH bpf-next 02/13] bpf: btf: Add BTF_KIND_FUNC and BTF_KIND_FUNC_PROTO

2018-10-12 Thread Yonghong Song
This patch adds BTF_KIND_FUNC and BTF_KIND_FUNC_PROTO
support to the type section. BTF_KIND_FUNC_PROTO is used
to specify the type of a function pointer. With this,
BTF has a complete set of C types (except float).

BTF_KIND_FUNC is used to specify the signature of a
defined subprogram. BTF_KIND_FUNC_PROTO can be referenced
by another type, e.g., a pointer type, and BTF_KIND_FUNC
type cannot be referenced by another type.

For both BTF_KIND_FUNC and BTF_KIND_FUNC_PROTO types,
the func return type is in t->type (where t is a
"struct btf_type" object). The func args are an array of
u32s immediately following object "t".

As a concrete example, for the C program below,
  $ cat test.c
  int foo(int (*bar)(int)) { return bar(5); }
with latest llvm trunk built with Debug mode, we have
  $ clang -target bpf -g -O2 -mllvm -debug-only=btf -c test.c
  Type Table:
  [1] FUNC name_off=1 info=0x0c01 size/type=2
  param_type=3
  [2] INT name_off=11 info=0x0100 size/type=4
  desc=0x0120
  [3] PTR name_off=0 info=0x0200 size/type=4
  [4] FUNC_PROTO name_off=0 info=0x0d01 size/type=2
  param_type=2

  String Table:
  0 :
  1 : foo
  5 : .text
  11 : int
  15 : test.c
  22 : int foo(int (*bar)(int)) { return bar(5); }

  FuncInfo Table:
  sec_name_off=5
  insn_offset= type_id=1

  ...

(Eventually we shall have bpftool to dump btf information
 like the above.)

Function "foo" has a FUNC type (type_id = 1).
The parameter of "foo" has type_id 3 which is PTR->FUNC_PROTO,
where FUNC_PROTO refers to function pointer "bar".

In FuncInfo Table, for section .text, the function,
with to-be-determined offset (marked as ),
has type_id=1 which refers to a FUNC type.
This way, the function signature is
available to both kernel and user space.
Here, the insn offset is not available during the dump time
as relocation is resolved pretty late in the compilation process.

Signed-off-by: Martin KaFai Lau 
Signed-off-by: Yonghong Song 
---
 include/uapi/linux/btf.h |   9 +-
 kernel/bpf/btf.c | 277 ++-
 2 files changed, 250 insertions(+), 36 deletions(-)

diff --git a/include/uapi/linux/btf.h b/include/uapi/linux/btf.h
index 972265f32871..63f8500e6f34 100644
--- a/include/uapi/linux/btf.h
+++ b/include/uapi/linux/btf.h
@@ -40,7 +40,8 @@ struct btf_type {
/* "size" is used by INT, ENUM, STRUCT and UNION.
 * "size" tells the size of the type it is describing.
 *
-* "type" is used by PTR, TYPEDEF, VOLATILE, CONST and RESTRICT.
+* "type" is used by PTR, TYPEDEF, VOLATILE, CONST, RESTRICT,
+* FUNC and FUNC_PROTO.
 * "type" is a type_id referring to another type.
 */
union {
@@ -64,8 +65,10 @@ struct btf_type {
 #define BTF_KIND_VOLATILE  9   /* Volatile */
 #define BTF_KIND_CONST 10  /* Const*/
 #define BTF_KIND_RESTRICT  11  /* Restrict */
-#define BTF_KIND_MAX   11
-#define NR_BTF_KINDS   12
+#define BTF_KIND_FUNC  12  /* Function */
+#define BTF_KIND_FUNC_PROTO13  /* Function Prototype   */
+#define BTF_KIND_MAX   13
+#define NR_BTF_KINDS   14
 
 /* For some specific BTF_KIND, "struct btf_type" is immediately
  * followed by extra data.
diff --git a/kernel/bpf/btf.c b/kernel/bpf/btf.c
index be406d8906ce..794a185f11bf 100644
--- a/kernel/bpf/btf.c
+++ b/kernel/bpf/btf.c
@@ -5,6 +5,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -259,6 +260,8 @@ static const char * const btf_kind_str[NR_BTF_KINDS] = {
[BTF_KIND_VOLATILE] = "VOLATILE",
[BTF_KIND_CONST]= "CONST",
[BTF_KIND_RESTRICT] = "RESTRICT",
+   [BTF_KIND_FUNC] = "FUNC",
+   [BTF_KIND_FUNC_PROTO]   = "FUNC_PROTO",
 };
 
 struct btf_kind_operations {
@@ -281,6 +284,9 @@ struct btf_kind_operations {
 static const struct btf_kind_operations * const kind_ops[NR_BTF_KINDS];
 static struct btf_type btf_void;
 
+static int btf_resolve(struct btf_verifier_env *env,
+  const struct btf_type *t, u32 type_id);
+
 static bool btf_type_is_modifier(const struct btf_type *t)
 {
/* Some of them is not strictly a C modifier
@@ -314,9 +320,20 @@ static bool btf_type_is_fwd(const struct btf_type *t)
return BTF_INFO_KIND(t->info) == BTF_KIND_FWD;
 }
 
+static bool btf_type_is_func(const struct btf_type *t)
+{
+   return BTF_INFO_KIND(t->info) == BTF_KIND_FUNC;
+}
+
+static bool btf_type_is_func_proto(const struct btf_type *t)
+{
+   return BTF_INFO_KIND(t->info) == BTF_KIND_FUNC_PROTO;
+}
+
 static bool btf_type_nosize(const struct btf_type *t)
 {
-   return btf_type_is_void(t) || btf_type_is_fwd(t);
+   return btf_type_is_void(t) 

[PATCH bpf-next 01/13] bpf: btf: Break up btf_type_is_void()

2018-10-12 Thread Yonghong Song
This patch breaks up btf_type_is_void() into
btf_type_is_void() and btf_type_is_fwd().

It also adds btf_type_nosize() to better describe it is
testing a type has nosize info.

Signed-off-by: Martin KaFai Lau 
---
 kernel/bpf/btf.c | 37 ++---
 1 file changed, 22 insertions(+), 15 deletions(-)

diff --git a/kernel/bpf/btf.c b/kernel/bpf/btf.c
index 378cef70341c..be406d8906ce 100644
--- a/kernel/bpf/btf.c
+++ b/kernel/bpf/btf.c
@@ -306,15 +306,22 @@ static bool btf_type_is_modifier(const struct btf_type *t)
 
 static bool btf_type_is_void(const struct btf_type *t)
 {
-   /* void => no type and size info.
-* Hence, FWD is also treated as void.
-*/
-   return t == _void || BTF_INFO_KIND(t->info) == BTF_KIND_FWD;
+   return t == _void;
+}
+
+static bool btf_type_is_fwd(const struct btf_type *t)
+{
+   return BTF_INFO_KIND(t->info) == BTF_KIND_FWD;
+}
+
+static bool btf_type_nosize(const struct btf_type *t)
+{
+   return btf_type_is_void(t) || btf_type_is_fwd(t);
 }
 
-static bool btf_type_is_void_or_null(const struct btf_type *t)
+static bool btf_type_nosize_or_null(const struct btf_type *t)
 {
-   return !t || btf_type_is_void(t);
+   return !t || btf_type_nosize(t);
 }
 
 /* union is only a special case of struct:
@@ -826,7 +833,7 @@ const struct btf_type *btf_type_id_size(const struct btf 
*btf,
u32 size = 0;
 
size_type = btf_type_by_id(btf, size_type_id);
-   if (btf_type_is_void_or_null(size_type))
+   if (btf_type_nosize_or_null(size_type))
return NULL;
 
if (btf_type_has_size(size_type)) {
@@ -842,7 +849,7 @@ const struct btf_type *btf_type_id_size(const struct btf 
*btf,
size = btf->resolved_sizes[size_type_id];
size_type_id = btf->resolved_ids[size_type_id];
size_type = btf_type_by_id(btf, size_type_id);
-   if (btf_type_is_void(size_type))
+   if (btf_type_nosize_or_null(size_type))
return NULL;
}
 
@@ -1164,7 +1171,7 @@ static int btf_modifier_resolve(struct btf_verifier_env 
*env,
}
 
/* "typedef void new_void", "const void"...etc */
-   if (btf_type_is_void(next_type))
+   if (btf_type_is_void(next_type) || btf_type_is_fwd(next_type))
goto resolved;
 
if (!env_type_is_resolve_sink(env, next_type) &&
@@ -1178,7 +1185,7 @@ static int btf_modifier_resolve(struct btf_verifier_env 
*env,
 * pretty print).
 */
if (!btf_type_id_size(btf, _type_id, _type_size) &&
-   !btf_type_is_void(btf_type_id_resolve(btf, _type_id))) {
+   !btf_type_nosize(btf_type_id_resolve(btf, _type_id))) {
btf_verifier_log_type(env, v->t, "Invalid type_id");
return -EINVAL;
}
@@ -1205,7 +1212,7 @@ static int btf_ptr_resolve(struct btf_verifier_env *env,
}
 
/* "void *" */
-   if (btf_type_is_void(next_type))
+   if (btf_type_is_void(next_type) || btf_type_is_fwd(next_type))
goto resolved;
 
if (!env_type_is_resolve_sink(env, next_type) &&
@@ -1235,7 +1242,7 @@ static int btf_ptr_resolve(struct btf_verifier_env *env,
}
 
if (!btf_type_id_size(btf, _type_id, _type_size) &&
-   !btf_type_is_void(btf_type_id_resolve(btf, _type_id))) {
+   !btf_type_nosize(btf_type_id_resolve(btf, _type_id))) {
btf_verifier_log_type(env, v->t, "Invalid type_id");
return -EINVAL;
}
@@ -1396,7 +1403,7 @@ static int btf_array_resolve(struct btf_verifier_env *env,
/* Check array->index_type */
index_type_id = array->index_type;
index_type = btf_type_by_id(btf, index_type_id);
-   if (btf_type_is_void_or_null(index_type)) {
+   if (btf_type_nosize_or_null(index_type)) {
btf_verifier_log_type(env, v->t, "Invalid index");
return -EINVAL;
}
@@ -1415,7 +1422,7 @@ static int btf_array_resolve(struct btf_verifier_env *env,
/* Check array->type */
elem_type_id = array->type;
elem_type = btf_type_by_id(btf, elem_type_id);
-   if (btf_type_is_void_or_null(elem_type)) {
+   if (btf_type_nosize_or_null(elem_type)) {
btf_verifier_log_type(env, v->t,
  "Invalid elem");
return -EINVAL;
@@ -1615,7 +1622,7 @@ static int btf_struct_resolve(struct btf_verifier_env 
*env,
const struct btf_type *member_type = btf_type_by_id(env->btf,
member_type_id);
 
-   if (btf_type_is_void_or_null(member_type)) {
+   if (btf_type_nosize_or_null(member_type)) {
btf_verifier_log_member(env, v->t, member,
"Invalid member");
return -EINVAL;
-- 
2.17.1



[PATCH bpf-next 04/13] tools/bpf: add btf func/func_proto unit tests in selftest test_btf

2018-10-12 Thread Yonghong Song
Add several BTF_KIND_FUNC and BTF_KIND_FUNC_PROTO
unit tests in bpf selftest test_btf.

Signed-off-by: Martin KaFai Lau 
Signed-off-by: Yonghong Song 
---
 tools/lib/bpf/btf.c|   4 +
 tools/testing/selftests/bpf/test_btf.c | 216 +
 2 files changed, 220 insertions(+)

diff --git a/tools/lib/bpf/btf.c b/tools/lib/bpf/btf.c
index 449591aa9900..33095fc1860b 100644
--- a/tools/lib/bpf/btf.c
+++ b/tools/lib/bpf/btf.c
@@ -165,6 +165,10 @@ static int btf_parse_type_sec(struct btf *btf, 
btf_print_fn_t err_log)
case BTF_KIND_ENUM:
next_type += vlen * sizeof(struct btf_enum);
break;
+   case BTF_KIND_FUNC:
+   case BTF_KIND_FUNC_PROTO:
+   next_type += vlen * sizeof(int);
+   break;
case BTF_KIND_TYPEDEF:
case BTF_KIND_PTR:
case BTF_KIND_FWD:
diff --git a/tools/testing/selftests/bpf/test_btf.c 
b/tools/testing/selftests/bpf/test_btf.c
index f42b3396d622..b6461c3c5e11 100644
--- a/tools/testing/selftests/bpf/test_btf.c
+++ b/tools/testing/selftests/bpf/test_btf.c
@@ -1374,6 +1374,222 @@ static struct btf_raw_test raw_tests[] = {
.map_create_err = true,
 },
 
+{
+   .descr = "func pointer #1",
+   .raw_types = {
+   BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4),  /* [1] */
+   BTF_TYPE_INT_ENC(0, 0, 0, 32, 4),   /* [2] */
+   /* int (*func)(int, unsigned int) */
+   BTF_TYPE_ENC(0, BTF_INFO_ENC(BTF_KIND_FUNC_PROTO, 0, 2), 1),
/* [3] */
+   1, 2,
+   BTF_TYPE_ENC(0, BTF_INFO_ENC(BTF_KIND_PTR, 0, 0), 3),   /* [4] 
*/
+   BTF_END_RAW,
+   },
+   .str_sec = "",
+   .str_sec_size = sizeof(""),
+   .map_type = BPF_MAP_TYPE_ARRAY,
+   .map_name = "func_type_check_btf",
+   .key_size = sizeof(int),
+   .value_size = sizeof(int),
+   .key_type_id = 1,
+   .value_type_id = 1,
+   .max_entries = 4,
+},
+
+{
+   .descr = "func pointer #2",
+   .raw_types = {
+   BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4),  /* [1] */
+   BTF_TYPE_INT_ENC(0, 0, 0, 32, 4),   /* [2] */
+   /* void (*func)(int, unsigned int, ) */
+   BTF_TYPE_ENC(0, BTF_INFO_ENC(BTF_KIND_FUNC_PROTO, 0, 3), 0),
/* [3] */
+   1, 2, 0,
+   BTF_TYPE_ENC(0, BTF_INFO_ENC(BTF_KIND_PTR, 0, 0), 3),   /* [4] 
*/
+   BTF_END_RAW,
+   },
+   .str_sec = "",
+   .str_sec_size = sizeof(""),
+   .map_type = BPF_MAP_TYPE_ARRAY,
+   .map_name = "func_type_check_btf",
+   .key_size = sizeof(int),
+   .value_size = sizeof(int),
+   .key_type_id = 1,
+   .value_type_id = 1,
+   .max_entries = 4,
+},
+
+{
+   .descr = "func pointer #3",
+   .raw_types = {
+   BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4),  /* [1] */
+   BTF_TYPE_INT_ENC(0, 0, 0, 32, 4),   /* [2] */
+   /* void (*func)(void, int, unsigned int) */
+   BTF_TYPE_ENC(0, BTF_INFO_ENC(BTF_KIND_FUNC_PROTO, 0, 3), 0),
/* [3] */
+   1, 0, 2,
+   BTF_TYPE_ENC(0, BTF_INFO_ENC(BTF_KIND_PTR, 0, 0), 3),   /* [4] 
*/
+   BTF_END_RAW,
+   },
+   .str_sec = "",
+   .str_sec_size = sizeof(""),
+   .map_type = BPF_MAP_TYPE_ARRAY,
+   .map_name = "func_type_check_btf",
+   .key_size = sizeof(int),
+   .value_size = sizeof(int),
+   .key_type_id = 1,
+   .value_type_id = 1,
+   .max_entries = 4,
+   .btf_load_err = true,
+   .err_str = "Invalid arg#2",
+},
+
+{
+   .descr = "func pointer #4",
+   .raw_types = {
+   BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4),  /* [1] */
+   BTF_TYPE_INT_ENC(0, 0, 0, 32, 4),   /* [2] */
+   /*
+* Testing:
+* BTF_KIND_CONST => BTF_KIND_TYPEDEF => BTF_KIND_PTR =>
+* BTF_KIND_FUNC_PROTO
+*/
+   /* typedef void (*func_ptr)(int, unsigned int) */
+   BTF_TYPE_ENC(0, BTF_INFO_ENC(BTF_KIND_TYPEDEF, 0, 0), 5),/* [3] 
*/
+   /* const func_ptr */
+   BTF_TYPE_ENC(0, BTF_INFO_ENC(BTF_KIND_CONST, 0, 0), 3), /* [4] 
*/
+   BTF_TYPE_ENC(0, BTF_INFO_ENC(BTF_KIND_PTR, 0, 0), 6),   /* [5] 
*/
+   BTF_TYPE_ENC(0, BTF_INFO_ENC(BTF_KIND_FUNC_PROTO, 0, 2), 0),
/* [6] */
+   1, 2,
+   BTF_END_RAW,
+   },
+   .str_sec = "",
+   .str_sec_size = sizeof(""),
+   .map_type = BPF_MAP_TYPE_ARRAY,
+   .map_name = "func_type_check_btf",
+   .ke

[PATCH bpf-next 09/13] tools/bpf: add support to read .BTF.ext sections

2018-10-12 Thread Yonghong Song
The .BTF section is already available to encode types.
These types can be used for map
pretty print. The whole .BTF will be passed to the
kernel as well for which kernel can verify and return
to the user space for pretty print etc.

Recently landed llvm patch "[BPF] Add BTF generation
for BPF target" (https://reviews.llvm.org/rL344366)
will generate .BTF section and one more section
.BTF.ext. The .BTF.ext section encodes function type
information and line information. For line information,
the actual source code is encoded in the section, which
makes compiler itself as an ideal place for section
generation.

The .BTF section does not depend on any other section,
and .BTF.ext has dependency on .BTF for strings and types.

The .BTF section can be directly loaded into the
kernel, and the .BTF.ext section cannot. The loader
may need to do some relocation and merging,
similar to merging multiple code sections, before
loading into the kernel.

In this patch, only func type info is processed.
The functionality is implemented in libbpf.
In this patch, the header for .BTF.ext is the same
as the one in LLVM
(https://github.com/llvm-mirror/llvm/blob/master/include/llvm/MC/MCBTFContext.h).

Signed-off-by: Yonghong Song 
---
 tools/lib/bpf/btf.c| 232 +
 tools/lib/bpf/btf.h|  31 ++
 tools/lib/bpf/libbpf.c |  53 +-
 3 files changed, 312 insertions(+), 4 deletions(-)

diff --git a/tools/lib/bpf/btf.c b/tools/lib/bpf/btf.c
index 33095fc1860b..4748e0bacd2b 100644
--- a/tools/lib/bpf/btf.c
+++ b/tools/lib/bpf/btf.c
@@ -37,6 +37,11 @@ struct btf {
int fd;
 };
 
+struct btf_ext {
+   void *func_info;
+   __u32 func_info_len;
+};
+
 static int btf_add_type(struct btf *btf, struct btf_type *t)
 {
if (btf->types_size - btf->nr_types < 2) {
@@ -397,3 +402,230 @@ const char *btf__name_by_offset(const struct btf *btf, 
__u32 offset)
else
return NULL;
 }
+
+static int btf_ext_validate_func_info(const struct btf_sec_func_info *sinfo,
+ __u32 size, btf_print_fn_t err_log)
+{
+   int sec_hdrlen = sizeof(struct btf_sec_func_info);
+   __u32 record_size = sizeof(struct bpf_func_info);
+   __u32 size_left = size, num_records;
+   __u64 total_record_size;
+
+   while (size_left) {
+   if (size_left < sec_hdrlen) {
+   elog("BTF.ext func_info header not found");
+   return -EINVAL;
+   }
+
+   num_records = sinfo->num_func_info;
+   if (num_records == 0) {
+   elog("incorrect BTF.ext num_func_info");
+   return -EINVAL;
+   }
+
+   total_record_size = sec_hdrlen +
+   (__u64)num_records * record_size;
+   if (size_left < total_record_size) {
+   elog("incorrect BTF.ext num_func_info");
+   return -EINVAL;
+   }
+
+   size_left -= total_record_size;
+   sinfo = (void *)sinfo + total_record_size;
+   }
+
+   return 0;
+}
+static int btf_ext_parse_hdr(__u8 *data, __u32 data_size,
+btf_print_fn_t err_log)
+{
+   const struct btf_ext_header *hdr = (struct btf_ext_header *)data;
+   const struct btf_sec_func_info *sinfo;
+   __u32 meta_left, last_func_info_pos;
+
+   if (data_size < sizeof(*hdr)) {
+   elog("BTF.ext header not found");
+   return -EINVAL;
+   }
+
+   if (hdr->magic != BTF_MAGIC) {
+   elog("Invalid BTF.ext magic:%x\n", hdr->magic);
+   return -EINVAL;
+   }
+
+   if (hdr->version != BTF_VERSION) {
+   elog("Unsupported BTF.ext version:%u\n", hdr->version);
+   return -ENOTSUP;
+   }
+
+   if (hdr->flags) {
+   elog("Unsupported BTF.ext flags:%x\n", hdr->flags);
+   return -ENOTSUP;
+   }
+
+   meta_left = data_size - sizeof(*hdr);
+   if (!meta_left) {
+   elog("BTF.ext has no data\n");
+   return -EINVAL;
+   }
+
+   if (meta_left < hdr->func_info_off) {
+   elog("Invalid BTF.ext func_info section offset:%u\n",
+hdr->func_info_off);
+   return -EINVAL;
+   }
+
+   if (hdr->func_info_off & 0x02) {
+   elog("BTF.ext func_info section is not aligned to 4 bytes\n");
+   return -EINVAL;
+   }
+
+   last_func_info_pos = sizeof(*hdr) + hdr->func_info_off +
+hdr->func_info_len;
+   if (last_func_info_pos > data_size) {
+   elog("Invalid BTF.ext func_i

[PATCH bpf-next 00/13] bpf: add btf func info support

2018-10-12 Thread Yonghong Song
The BTF support was added to kernel by Commit 69b693f0aefa
("bpf: btf: Introduce BPF Type Format (BTF)"), which introduced
.BTF section into ELF file and is primarily
used for map pretty print.
pahole is used to convert dwarf to BTF for ELF files.

The next step would be add func type info and debug line info
into BTF. For debug line info, it is desirable to encode
source code directly in the BTF to ease deployment and
introspection.

The func type and debug line info are relative to byte code offset.
Also since byte codes may need to be relocated by the loader,
func info and line info are placed in a different section,
.BTF.ext, so the loader could manupilate it according to how
byte codes are placed, before loading into the kernel.

LLVM commit https://reviews.llvm.org/rL344366 (in llvm trunk)
now can generate type/func/line info.
For the below example, with a llvm compiler built with Debug mode,
the following is generated:

  -bash-4.2$ cat test.c
  int foo(int (*bar)(int)) { return bar(5); }
  -bash-4.2$ clang -target bpf -g -O2 -mllvm -debug-only=btf -c test.c
  Type Table:
  [1] FUNC name_off=1 info=0x0c01 size/type=2
param_type=3
  [2] INT name_off=11 info=0x0100 size/type=4
desc=0x0120
  [3] PTR name_off=0 info=0x0200 size/type=4
  [4] FUNC_PROTO name_off=0 info=0x0d01 size/type=2
param_type=2

  String Table:
  0 : 
  1 : foo
  5 : .text
  11 : int
  15 : test.c
  22 : int foo(int (*bar)(int)) { return bar(5); }

  FuncInfo Table:
  sec_name_off=5
insn_offset= type_id=1

  LineInfo Table:
  sec_name_off=5
insn_offset= file_name_off=15 line_off=22 line_num=1 
column_num=0
insn_offset= file_name_off=15 line_off=22 line_num=1 
column_num=35
insn_offset= file_name_off=15 line_off=22 line_num=1 
column_num=28

In the above, type and string tables are in .BTF section, and
func and line info tables in .BTF.ext. The "" is the
insn offset which is not available during the dump time but
resolved during later compilation process.
Following the format specification at Patch #9 and examine the
raw data in .BTF.ext section, we have
  FuncInfo Table:
  sec_name_off=5
insn_offset=0 type_id=1

  LineInfo Table:
  sec_name_off=5
insn_offset=0  file_name_off=15 line_off=22 line_num=1 column_num=0
insn_offset=8  file_name_off=15 line_off=22 line_num=1 column_num=35
insn_offset=24 file_name_off=15 line_off=22 line_num=1 column_num=28
In the above insn_offset is the byte offset.

With this support, better ksym for bpf programs and functions can be
generated. Below is a demonstration from Patch #13.
  $ bpftool prog dump jited id 1
  int _dummy_tracepoint(struct dummy_tracepoint_args * ):
  bpf_prog_b07ccb89267cf242__dummy_tracepoint:
 0:   push   %rbp
 1:   mov%rsp,%rbp
..
3c:   add$0x28,%rbp
40:   leaveq
41:   retq

  int test_long_fname_1(struct dummy_tracepoint_args * ):
  bpf_prog_2dcecc18072623fc_test_long_fname_1:
 0:   push   %rbp
 1:   mov%rsp,%rbp
..
3a:   add$0x28,%rbp
3e:   leaveq
3f:   retq

  int test_long_fname_2(struct dummy_tracepoint_args * ):
  bpf_prog_89d64e4abf0f0126_test_long_fname_2:
 0:   push   %rbp
 1:   mov%rsp,%rbp
..
80:   add$0x28,%rbp
84:   leaveq
85:   retq

For the patchset,
Patch #1  refactors the code to break up btf_type_is_void().
Patch #2  introduces new BTF types BTF_KIND_FUNC and BTF_KIND_FUNC_PROTO.
Patch #3  syncs btf.h header to tools directory.
Patch #4  adds btf func/func_proto self tests in test_btf.
Patch #5  adds kernel interface to load func_info to kernel
  and pass func_info to userspace.
Patch #6  syncs bpf.h header to tools directory.
Patch #7  adds news btf/func_info related fields in libbpf
  program load function.
Patch #8  extends selftest test_btf to test load/retrieve func_type info.
Patch #9  adds .BTF.ext func info support.
Patch #10 changes Makefile to avoid using pahole if llvm is capable of
  generating BTF sections.
Patch #11 refactors to have btf_get_from_id() in libbpf for reuse.
Patch #12 enhance test_btf file testing to test func info.
Patch #13 adds bpftool support for func signature dump.

Yonghong Song (13):
  bpf: btf: Break up btf_type_is_void()
  bpf: btf: Add BTF_KIND_FUNC and BTF_KIND_FUNC_PROTO
  tools/bpf: sync kernel btf.h header
  tools/bpf: add btf func/func_proto unit tests in selftest test_btf
  bpf: get better bpf_prog ksyms based on btf func type_id
  tools/bpf: sync kernel uapi bpf.h header to tools directory
  tools/bpf: add new fields for program load in lib/bpf
  tools/bpf: extends test_btf to test load/retrieve func_type info
  tools/bpf: add support to read .BTF.ext sections
  tools/bpf: do not use pahole if clang/llvm can generate BTF sections
  tools/bpf: refactor to implement btf_get_

[PATCH bpf-next] tools/bpf: use proper type and uapi perf_event.h header for libbpf

2018-10-09 Thread Yonghong Song
Use __u32 instead u32 in libbpf.c and also use
uapi perf_event.h instead of tools/perf/perf-sys.h.

Signed-off-by: Yonghong Song 
---
 tools/lib/bpf/Makefile | 2 +-
 tools/lib/bpf/libbpf.c | 8 
 2 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/tools/lib/bpf/Makefile b/tools/lib/bpf/Makefile
index 6ad27257fd67..79d84413ddf2 100644
--- a/tools/lib/bpf/Makefile
+++ b/tools/lib/bpf/Makefile
@@ -69,7 +69,7 @@ FEATURE_USER = .libbpf
 FEATURE_TESTS = libelf libelf-mmap bpf reallocarray
 FEATURE_DISPLAY = libelf bpf
 
-INCLUDES = -I. -I$(srctree)/tools/include 
-I$(srctree)/tools/arch/$(ARCH)/include/uapi -I$(srctree)/tools/include/uapi 
-I$(srctree)/tools/perf
+INCLUDES = -I. -I$(srctree)/tools/include 
-I$(srctree)/tools/arch/$(ARCH)/include/uapi -I$(srctree)/tools/include/uapi
 FEATURE_CHECK_CFLAGS-bpf = $(INCLUDES)
 
 check_feat := 1
diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c
index ceb918c14d80..176cf5523728 100644
--- a/tools/lib/bpf/libbpf.c
+++ b/tools/lib/bpf/libbpf.c
@@ -19,7 +19,6 @@
 #include 
 #include 
 #include 
-#include 
 #include 
 #include 
 #include 
@@ -27,6 +26,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -169,7 +169,7 @@ static LIST_HEAD(bpf_objects_list);
 
 struct bpf_object {
char license[64];
-   u32 kern_version;
+   __u32 kern_version;
 
struct bpf_program *programs;
size_t nr_programs;
@@ -540,7 +540,7 @@ static int
 bpf_object__init_kversion(struct bpf_object *obj,
  void *data, size_t size)
 {
-   u32 kver;
+   __u32 kver;
 
if (size != sizeof(kver)) {
pr_warning("invalid kver section in %s\n", obj->path);
@@ -1295,7 +1295,7 @@ static int bpf_object__collect_reloc(struct bpf_object 
*obj)
 static int
 load_program(enum bpf_prog_type type, enum bpf_attach_type 
expected_attach_type,
 const char *name, struct bpf_insn *insns, int insns_cnt,
-char *license, u32 kern_version, int *pfd, int prog_ifindex)
+char *license, __u32 kern_version, int *pfd, int prog_ifindex)
 {
struct bpf_load_program_attr load_attr;
char *cp, errmsg[STRERR_BUFSIZE];
-- 
2.17.1



Re: [PATCH bpf-next 0/6] Consistent prefixes for libbpf interfaces

2018-10-09 Thread Yonghong Song


On 10/4/18 7:22 AM, Daniel Borkmann wrote:
> [ +Yonghong ]
> 
> On 10/04/2018 12:26 AM, Andrey Ignatov wrote:
>> This patch set renames a few interfaces in libbpf, mostly netlink related,
>> so that all symbols provided by the library have only three possible
>> prefixes:
>>
>> % nm -D tools/lib/bpf/libbpf.so  | \
>>  awk '$2 == "T" {sub(/[_\(].*/, "", $3); if ($3) print $3}' | \
>>  sort | \
>>  uniq -c
>>   91 bpf
>>8 btf
>>   14 libbpf
>>
>> libbpf is used more and more outside kernel tree. That means the library
>> should follow good practices in library design and implementation to
>> play well with third party code that uses it.
>>
>> One of such practices is to have a common prefix (or a few) for every
>> interface, function or data structure, library provides. It helps to
>> avoid name conflicts with other libraries and keeps API/ABI consistent.
>>
>> Inconsistent names in libbpf already cause problems in real life. E.g.
>> an application can't use both libbpf and libnl due to conflicting
>> symbols (specifically nla_parse, nla_parse_nested and a few others).
>>
>> Some of problematic global symbols are not part of ABI and can be
>> restricted from export with either visibility attribute/pragma or export
>> map (what is useful by itself and can be done in addition). That won't
>> solve the problem for those that are part of ABI though. Also export
>> restrictions would help only in DSO case. If third party application links
>> libbpf statically it won't help, and people do it (e.g. Facebook links
>> most of libraries statically, including libbpf).
>>
>> libbpf already uses the following prefixes for its interfaces:
>> * bpf_ for bpf system call wrappers, program/map/elf-object
>>abstractions and a few other things;
>> * btf_ for BTF related API;
>> * libbpf_ for everything else.
>>
>> The patch adds libbpf_ prefix to interfaces that use none of mentioned
>> above prefixes and don't fit well into the first two categories.
>>
>> Long term benefits of having common prefix should outweigh possible
>> inconvenience of changing API for those functions now.
>>
>> Patches 2-4 add libbpf_ prefix to libbpf interfaces: separate patch per
>> header. Other patches are simple improvements in API.
>>
>>
>> Andrey Ignatov (6):
>>libbpf: Move __dump_nlmsg_t from API to implementation
>>libbpf: Consistent prefixes for interfaces in libbpf.h.
>>libbpf: Consistent prefixes for interfaces in nlattr.h.
>>libbpf: Consistent prefixes for interfaces in str_error.h.
>>libbpf: Make include guards consistent
>>libbpf: Use __u32 instead of u32 in bpf_program__load
>>
>>   tools/bpf/bpftool/net.c| 41 ++-
>>   tools/bpf/bpftool/netlink_dumper.c | 32 ---
>>   tools/lib/bpf/bpf.h|  6 +--
>>   tools/lib/bpf/btf.h|  6 +--
>>   tools/lib/bpf/libbpf.c | 22 +-
>>   tools/lib/bpf/libbpf.h | 31 +++---
>>   tools/lib/bpf/netlink.c| 48 --
>>   tools/lib/bpf/nlattr.c | 64 +++--
>>   tools/lib/bpf/nlattr.h | 65 +++---
>>   tools/lib/bpf/str_error.c  |  2 +-
>>   tools/lib/bpf/str_error.h  |  8 ++--
>>   11 files changed, 171 insertions(+), 154 deletions(-)
> 
> Overall agree that this is needed, and I've therefore applied the
> set, thanks for cleaning up, Andrey!
> 
> But, I would actually like to see this going one step further, in
> particular, we should keep all the netlink related stuff inside
> libbpf-/only/. Meaning, the goal of libbpf is not to provide yet
> another set of netlink primitives but instead e.g. for the bpftool
> dumper this should be abstracted away such that we pass in a callback
> from bpftool side and have an iterator object which will then be
> populated from inside the libbpf logic, meaning, bpftool shouldn't
> even be aware of anything netlink there.

Agreed. This indeed make sense, the user really only cares a few fields
like devname/id, attachment_type, prog_id, etc. I will take a look at
this later if nobody works on it.

> 
> Thanks,
> Daniel
> 


[PATCH bpf-next] bpf: permit CGROUP_DEVICE programs accessing helper bpf_get_current_cgroup_id()

2018-09-27 Thread Yonghong Song
Currently, helper bpf_get_current_cgroup_id() is not permitted
for CGROUP_DEVICE type of programs. If the helper is used
in such cases, the verifier will log the following error:

  0: (bf) r6 = r1
  1: (69) r7 = *(u16 *)(r6 +0)
  2: (85) call bpf_get_current_cgroup_id#80
  unknown func bpf_get_current_cgroup_id#80

The bpf_get_current_cgroup_id() is useful for CGROUP_DEVICE
type of programs in order to customize action based on cgroup id.
This patch added such a support.

Cc: Roman Gushchin 
Signed-off-by: Yonghong Song 
---
 kernel/bpf/cgroup.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/kernel/bpf/cgroup.c b/kernel/bpf/cgroup.c
index 065c3d9ff8eb..00f6ed2e4f9a 100644
--- a/kernel/bpf/cgroup.c
+++ b/kernel/bpf/cgroup.c
@@ -707,6 +707,8 @@ cgroup_dev_func_proto(enum bpf_func_id func_id, const 
struct bpf_prog *prog)
return _get_current_uid_gid_proto;
case BPF_FUNC_get_local_storage:
return _get_local_storage_proto;
+   case BPF_FUNC_get_current_cgroup_id:
+   return _get_current_cgroup_id_proto;
case BPF_FUNC_trace_printk:
if (capable(CAP_SYS_ADMIN))
return bpf_get_trace_printk_proto();
-- 
2.17.1



[PATCH bpf-next] samples/bpf: fix a compilation failure

2018-09-17 Thread Yonghong Song
samples/bpf build failed with the following errors:

  $ make samples/bpf/
  ...
  HOSTCC  samples/bpf/sockex3_user.o
  /data/users/yhs/work/net-next/samples/bpf/sockex3_user.c:16:8: error: 
redefinition of ‘struct bpf_flow_keys’
   struct bpf_flow_keys {
  ^
  In file included from 
/data/users/yhs/work/net-next/samples/bpf/sockex3_user.c:4:0:
  ./usr/include/linux/bpf.h:2338:9: note: originally defined here
struct bpf_flow_keys *flow_keys;
   ^
  make[3]: *** [samples/bpf/sockex3_user.o] Error 1

Commit d58e468b1112d ("flow_dissector: implements flow dissector BPF hook")
introduced struct bpf_flow_keys in include/uapi/linux/bpf.h and hence
caused the naming conflict with samples/bpf/sockex3_user.c.

The fix is to rename struct bpf_flow_keys in samples/bpf/sockex3_user.c
to flow_keys to avoid the conflict.

Signed-off-by: Yonghong Song 
---
 samples/bpf/sockex3_user.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/samples/bpf/sockex3_user.c b/samples/bpf/sockex3_user.c
index 5ba3ae9d180b..22f74d0e1493 100644
--- a/samples/bpf/sockex3_user.c
+++ b/samples/bpf/sockex3_user.c
@@ -13,7 +13,7 @@
 #define PARSE_IP_PROG_FD (prog_fd[0])
 #define PROG_ARRAY_FD (map_fd[0])
 
-struct bpf_flow_keys {
+struct flow_keys {
__be32 src;
__be32 dst;
union {
@@ -64,7 +64,7 @@ int main(int argc, char **argv)
(void) f;
 
for (i = 0; i < 5; i++) {
-   struct bpf_flow_keys key = {}, next_key;
+   struct flow_keys key = {}, next_key;
struct pair value;
 
sleep(1);
-- 
2.17.1



[PATCH bpf-next v2] tools/bpf: bpftool: improve output format for bpftool net

2018-09-17 Thread Yonghong Song
This is a followup patch for Commit f6f3bac08ff9
("tools/bpf: bpftool: add net support").
Some improvements are made for the bpftool net output.
Specially, plain output is more concise such that
per attachment should nicely fit in one line.
Compared to previous output, the prog tag is removed
since it can be easily obtained with program id.
Similar to xdp attachments, the device name is added
to tc attachments.

The bpf program attached through shared block
mechanism is supported as well.
  $ ip link add dev v1 type veth peer name v2
  $ tc qdisc add dev v1 ingress_block 10 egress_block 20 clsact
  $ tc qdisc add dev v2 ingress_block 10 egress_block 20 clsact
  $ tc filter add block 10 protocol ip prio 25 bpf obj bpf_shared.o sec ingress 
flowid 1:1
  $ tc filter add block 20 protocol ip prio 30 bpf obj bpf_cyclic.o sec 
classifier flowid 1:1
  $ bpftool net
  xdp:

  tc:
  v2(7) clsact/ingress bpf_shared.o:[ingress] id 23
  v2(7) clsact/egress bpf_cyclic.o:[classifier] id 24
  v1(8) clsact/ingress bpf_shared.o:[ingress] id 23
  v1(8) clsact/egress bpf_cyclic.o:[classifier] id 24

The documentation and "bpftool net help" are updated
to make it clear that current implementation only
supports xdp and tc attachments. For programs
attached to cgroups, "bpftool cgroup" can be used
to dump attachments. For other programs e.g.
sk_{filter,skb,msg,reuseport} and lwt/seg6,
iproute2 tools should be used.

The new output:
  $ bpftool net
  xdp:
  eth0(2) driver id 198

  tc:
  eth0(2) clsact/ingress fbflow_icmp id 335 act [{icmp_action id 336}]
  eth0(2) clsact/egress fbflow_egress id 334
  $ bpftool -jp net
  [{
"xdp": [{
"devname": "eth0",
"ifindex": 2,
"mode": "driver",
"id": 198
}
],
"tc": [{
"devname": "eth0",
"ifindex": 2,
"kind": "clsact/ingress",
"name": "fbflow_icmp",
"id": 335,
"act": [{
"name": "icmp_action",
"id": 336
}
]
    },{
    "devname": "eth0",
"ifindex": 2,
"kind": "clsact/egress",
"name": "fbflow_egress",
"id": 334
}
]
}
  ]

Signed-off-by: Yonghong Song 
---
 .../bpf/bpftool/Documentation/bpftool-net.rst |  78 +++--
 tools/bpf/bpftool/main.h  |   3 +-
 tools/bpf/bpftool/net.c   | 103 --
 tools/bpf/bpftool/netlink_dumper.c|  85 +++
 tools/bpf/bpftool/netlink_dumper.h|  22 ++--
 5 files changed, 161 insertions(+), 130 deletions(-)

Changelogs:
 v1 -> v2:
. Addressed several output format suggestions from Daniel

diff --git a/tools/bpf/bpftool/Documentation/bpftool-net.rst 
b/tools/bpf/bpftool/Documentation/bpftool-net.rst
index 48a61837a264..408ec30d8872 100644
--- a/tools/bpf/bpftool/Documentation/bpftool-net.rst
+++ b/tools/bpf/bpftool/Documentation/bpftool-net.rst
@@ -26,9 +26,20 @@ NET COMMANDS
 DESCRIPTION
 ===
**bpftool net { show | list } [ dev name ]**
- List all networking device driver and tc attachment in the 
system.
-
-  Output will start with all xdp program attachment, followed 
by
+  List bpf program attachments in the kernel networking 
subsystem.
+
+  Currently, only device driver xdp attachments and tc filter
+  classification/action attachments are implemented, i.e., for
+  program types **BPF_PROG_TYPE_SCHED_CLS**,
+  **BPF_PROG_TYPE_SCHED_ACT** and **BPF_PROG_TYPE_XDP**.
+  For programs attached to a particular cgroup, e.g.,
+  **BPF_PROG_TYPE_CGROUP_SKB**, **BPF_PROG_TYPE_CGROUP_SOCK**,
+  **BPF_PROG_TYPE_SOCK_OPS** and 
**BPF_PROG_TYPE_CGROUP_SOCK_ADDR**,
+  users can use **bpftool cgroup** to dump cgroup attachments.
+  For sk_{filter, skb, msg, reuseport} and lwt/seg6
+  bpf programs, users should consult other tools, e.g., 
iproute2.
+
+  The current output will start with all xdp program 
attachments, followed by
   all tc class/qdisc bpf program attachments. Both xdp 
programs and
   tc programs are ordered based on ifindex number. If multiple 
bpf
   programs attached to the same networking device through **tc 
filter**,
@@ -61,21 +72,15 @@ EXAMPLES
 
 ::
 
-  xdp [
-  ifinde

Re: [PATCH bpf-next] tools/bpf: bpftool: improve output format for bpftool net

2018-09-17 Thread Yonghong Song


On 9/17/18 3:19 AM, Daniel Borkmann wrote:
> On 09/14/2018 11:49 PM, Yonghong Song wrote:
>> This is a followup patch for Commit f6f3bac08ff9
>> ("tools/bpf: bpftool: add net support").
>> Some improvements are made for the bpftool net output.
>> Specially, plain output is more concise such that
>> per attachment should nicely fit in one line.
>> Compared to previous output, the prog tag is removed
>> since it can be easily obtained with program id.
>> Similar to xdp attachments, the device name is added
>> to tc_filters attachments.
>>
>> The bpf program attached through shared block
>> mechanism is supported as well.
>>$ ip link add dev v1 type veth peer name v2
>>$ tc qdisc add dev v1 ingress_block 10 egress_block 20 clsact
>>$ tc qdisc add dev v2 ingress_block 10 egress_block 20 clsact
>>$ tc filter add block 10 protocol ip prio 25 bpf obj bpf_shared.o sec 
>> ingress flowid 1:1
>>$ tc filter add block 20 protocol ip prio 30 bpf obj bpf_cyclic.o sec 
>> classifier flowid 1:1
>>$ bpftool net
>>xdp [
>>]
>>tc_filters [
>> v2(7) qdisc_clsact_ingress bpf_shared.o:[ingress] id 23
>> v2(7) qdisc_clsact_egress bpf_cyclic.o:[classifier] id 24
>> v1(8) qdisc_clsact_ingress bpf_shared.o:[ingress] id 23
>> v1(8) qdisc_clsact_egress bpf_cyclic.o:[classifier] id 24
> 
> Just one minor note for this one here, do we even need the "qdisc_" prefix? 
> Couldn't it just simply
> be "clsact/ingress", "clsact/egress", "htb" etc?

Will do.

> 
>>]
>>
>> The documentation and "bpftool net help" are updated
>> to make it clear that current implementation only
>> supports xdp and tc attachments. For programs
>> attached to cgroups, "bpftool cgroup" can be used
>> to dump attachments. For other programs e.g.
>> sk_{filter,skb,msg,reuseport} and lwt/seg6,
>> iproute2 tools should be used.
>>
>> The new output:
>>$ bpftool net
>>xdp [
>> eth0(2) id/drv 198
> 
> Could we change the "id/{drv,offload,generic} xyz" into e.g. "eth0(2) 
> {driver,offload,generic} id 198",
> meaning, the "id xyz" being a child of either "driver", "offload" or 
> "generic". Reason would be two-fold:
> i) we can keep the "id xyz" notion consistent as used under "tc_filters", and 
> ii) it allows to put further
> information aside from just "id" member under "driver", "offload" or 
> "generic" in the future.

Will do.

> 
>>]
>>tc_filters [
> 
> Nit: can we use just "tc" for the above? Main use case would be clsact with 
> one of its two hooks anyway,
> and the term "filter" is sort of tc historic; while being correct bpf progs 
> would do much more than just
> filtering, and context is pretty clear anyway from qdisc that we subsequently 
> dump.

Make sense.

Will address all these comments and submit a revision soon. Thanks!

> 
>> eth0(2) qdisc_clsact_ingress fbflow_icmp id 335 act [{icmp_action id 
>> 336}]
>> eth0(2) qdisc_clsact_egress fbflow_egress id 334
>>]
>>$ bpftool -jp net
>>[{
>>  "xdp": [{
>>  "devname": "eth0",
>>  "ifindex": 2,
>>  "id/drv": 198
>>  }
>>  ],
>>  "tc_filters": [{
>>  "devname": "eth0",
>>  "ifindex": 2,
>>  "kind": "qdisc_clsact_ingress",
>>  "name": "fbflow_icmp",
>>  "id": 335,
>>  "act": [{
>>  "name": "icmp_action",
>>  "id": 336
>>  }
>>  ]
>>  },{
>>  "devname": "eth0",
>>  "ifindex": 2,
>>  "kind": "qdisc_clsact_egress",
>>  "name": "fbflow_egress",
>>  "id": 334
>>  }
>>  ]
>>  }
>>]
>>
>> Signed-off-by: Yonghong Song 


  1   2   3   4   5   6   >