Skip to content

Commit c7655df

Browse files
committed
Merge branch 'Support riscv libbpf USDT arg parsing logic'
Pu Lehui says: ==================== patch 1 fix a minor issue where usdt_cookie is cast to 32 bits. patch 2 add support riscv libbpf USDT argument parsing logic, both RV32 and RV64 tests have been passed as like follow: # ./test_progs -t usdt raspberrypi#169 usdt:OK Summary: 1/4 PASSED, 0 SKIPPED, 0 FAILED ==================== Signed-off-by: Andrii Nakryiko <[email protected]>
2 parents dcf456c + 58ca8b0 commit c7655df

File tree

3 files changed

+113
-6
lines changed

3 files changed

+113
-6
lines changed

tools/lib/bpf/libbpf.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10993,7 +10993,7 @@ struct bpf_link *bpf_program__attach_usdt(const struct bpf_program *prog,
1099310993
char resolved_path[512];
1099410994
struct bpf_object *obj = prog->obj;
1099510995
struct bpf_link *link;
10996-
long usdt_cookie;
10996+
__u64 usdt_cookie;
1099710997
int err;
1099810998

1099910999
if (!OPTS_VALID(opts, bpf_uprobe_opts))

tools/lib/bpf/libbpf_internal.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -571,6 +571,6 @@ struct bpf_link * usdt_manager_attach_usdt(struct usdt_manager *man,
571571
const struct bpf_program *prog,
572572
pid_t pid, const char *path,
573573
const char *usdt_provider, const char *usdt_name,
574-
long usdt_cookie);
574+
__u64 usdt_cookie);
575575

576576
#endif /* __LIBBPF_LIBBPF_INTERNAL_H */

tools/lib/bpf/usdt.c

Lines changed: 111 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,11 @@
1010
#include <linux/ptrace.h>
1111
#include <linux/kernel.h>
1212

13+
/* s8 will be marked as poison while it's a reg of riscv */
14+
#if defined(__riscv)
15+
#define rv_s8 s8
16+
#endif
17+
1318
#include "bpf.h"
1419
#include "libbpf.h"
1520
#include "libbpf_common.h"
@@ -557,10 +562,10 @@ static int parse_usdt_note(Elf *elf, const char *path, long base_addr,
557562
GElf_Nhdr *nhdr, const char *data, size_t name_off, size_t desc_off,
558563
struct usdt_note *usdt_note);
559564

560-
static int parse_usdt_spec(struct usdt_spec *spec, const struct usdt_note *note, long usdt_cookie);
565+
static int parse_usdt_spec(struct usdt_spec *spec, const struct usdt_note *note, __u64 usdt_cookie);
561566

562567
static int collect_usdt_targets(struct usdt_manager *man, Elf *elf, const char *path, pid_t pid,
563-
const char *usdt_provider, const char *usdt_name, long usdt_cookie,
568+
const char *usdt_provider, const char *usdt_name, __u64 usdt_cookie,
564569
struct usdt_target **out_targets, size_t *out_target_cnt)
565570
{
566571
size_t off, name_off, desc_off, seg_cnt = 0, lib_seg_cnt = 0, target_cnt = 0;
@@ -939,7 +944,7 @@ static int allocate_spec_id(struct usdt_manager *man, struct hashmap *specs_hash
939944
struct bpf_link *usdt_manager_attach_usdt(struct usdt_manager *man, const struct bpf_program *prog,
940945
pid_t pid, const char *path,
941946
const char *usdt_provider, const char *usdt_name,
942-
long usdt_cookie)
947+
__u64 usdt_cookie)
943948
{
944949
int i, fd, err, spec_map_fd, ip_map_fd;
945950
LIBBPF_OPTS(bpf_uprobe_opts, opts);
@@ -1141,7 +1146,7 @@ static int parse_usdt_note(Elf *elf, const char *path, long base_addr,
11411146

11421147
static int parse_usdt_arg(const char *arg_str, int arg_num, struct usdt_arg_spec *arg);
11431148

1144-
static int parse_usdt_spec(struct usdt_spec *spec, const struct usdt_note *note, long usdt_cookie)
1149+
static int parse_usdt_spec(struct usdt_spec *spec, const struct usdt_note *note, __u64 usdt_cookie)
11451150
{
11461151
const char *s;
11471152
int len;
@@ -1400,6 +1405,108 @@ static int parse_usdt_arg(const char *arg_str, int arg_num, struct usdt_arg_spec
14001405
return len;
14011406
}
14021407

1408+
#elif defined(__riscv)
1409+
1410+
static int calc_pt_regs_off(const char *reg_name)
1411+
{
1412+
static struct {
1413+
const char *name;
1414+
size_t pt_regs_off;
1415+
} reg_map[] = {
1416+
{ "ra", offsetof(struct user_regs_struct, ra) },
1417+
{ "sp", offsetof(struct user_regs_struct, sp) },
1418+
{ "gp", offsetof(struct user_regs_struct, gp) },
1419+
{ "tp", offsetof(struct user_regs_struct, tp) },
1420+
{ "a0", offsetof(struct user_regs_struct, a0) },
1421+
{ "a1", offsetof(struct user_regs_struct, a1) },
1422+
{ "a2", offsetof(struct user_regs_struct, a2) },
1423+
{ "a3", offsetof(struct user_regs_struct, a3) },
1424+
{ "a4", offsetof(struct user_regs_struct, a4) },
1425+
{ "a5", offsetof(struct user_regs_struct, a5) },
1426+
{ "a6", offsetof(struct user_regs_struct, a6) },
1427+
{ "a7", offsetof(struct user_regs_struct, a7) },
1428+
{ "s0", offsetof(struct user_regs_struct, s0) },
1429+
{ "s1", offsetof(struct user_regs_struct, s1) },
1430+
{ "s2", offsetof(struct user_regs_struct, s2) },
1431+
{ "s3", offsetof(struct user_regs_struct, s3) },
1432+
{ "s4", offsetof(struct user_regs_struct, s4) },
1433+
{ "s5", offsetof(struct user_regs_struct, s5) },
1434+
{ "s6", offsetof(struct user_regs_struct, s6) },
1435+
{ "s7", offsetof(struct user_regs_struct, s7) },
1436+
{ "s8", offsetof(struct user_regs_struct, rv_s8) },
1437+
{ "s9", offsetof(struct user_regs_struct, s9) },
1438+
{ "s10", offsetof(struct user_regs_struct, s10) },
1439+
{ "s11", offsetof(struct user_regs_struct, s11) },
1440+
{ "t0", offsetof(struct user_regs_struct, t0) },
1441+
{ "t1", offsetof(struct user_regs_struct, t1) },
1442+
{ "t2", offsetof(struct user_regs_struct, t2) },
1443+
{ "t3", offsetof(struct user_regs_struct, t3) },
1444+
{ "t4", offsetof(struct user_regs_struct, t4) },
1445+
{ "t5", offsetof(struct user_regs_struct, t5) },
1446+
{ "t6", offsetof(struct user_regs_struct, t6) },
1447+
};
1448+
int i;
1449+
1450+
for (i = 0; i < ARRAY_SIZE(reg_map); i++) {
1451+
if (strcmp(reg_name, reg_map[i].name) == 0)
1452+
return reg_map[i].pt_regs_off;
1453+
}
1454+
1455+
pr_warn("usdt: unrecognized register '%s'\n", reg_name);
1456+
return -ENOENT;
1457+
}
1458+
1459+
static int parse_usdt_arg(const char *arg_str, int arg_num, struct usdt_arg_spec *arg)
1460+
{
1461+
char *reg_name = NULL;
1462+
int arg_sz, len, reg_off;
1463+
long off;
1464+
1465+
if (sscanf(arg_str, " %d @ %ld ( %m[a-z0-9] ) %n", &arg_sz, &off, &reg_name, &len) == 3) {
1466+
/* Memory dereference case, e.g., -8@-88(s0) */
1467+
arg->arg_type = USDT_ARG_REG_DEREF;
1468+
arg->val_off = off;
1469+
reg_off = calc_pt_regs_off(reg_name);
1470+
free(reg_name);
1471+
if (reg_off < 0)
1472+
return reg_off;
1473+
arg->reg_off = reg_off;
1474+
} else if (sscanf(arg_str, " %d @ %ld %n", &arg_sz, &off, &len) == 2) {
1475+
/* Constant value case, e.g., 4@5 */
1476+
arg->arg_type = USDT_ARG_CONST;
1477+
arg->val_off = off;
1478+
arg->reg_off = 0;
1479+
} else if (sscanf(arg_str, " %d @ %m[a-z0-9] %n", &arg_sz, &reg_name, &len) == 2) {
1480+
/* Register read case, e.g., -8@a1 */
1481+
arg->arg_type = USDT_ARG_REG;
1482+
arg->val_off = 0;
1483+
reg_off = calc_pt_regs_off(reg_name);
1484+
free(reg_name);
1485+
if (reg_off < 0)
1486+
return reg_off;
1487+
arg->reg_off = reg_off;
1488+
} else {
1489+
pr_warn("usdt: unrecognized arg #%d spec '%s'\n", arg_num, arg_str);
1490+
return -EINVAL;
1491+
}
1492+
1493+
arg->arg_signed = arg_sz < 0;
1494+
if (arg_sz < 0)
1495+
arg_sz = -arg_sz;
1496+
1497+
switch (arg_sz) {
1498+
case 1: case 2: case 4: case 8:
1499+
arg->arg_bitshift = 64 - arg_sz * 8;
1500+
break;
1501+
default:
1502+
pr_warn("usdt: unsupported arg #%d (spec '%s') size: %d\n",
1503+
arg_num, arg_str, arg_sz);
1504+
return -EINVAL;
1505+
}
1506+
1507+
return len;
1508+
}
1509+
14031510
#else
14041511

14051512
static int parse_usdt_arg(const char *arg_str, int arg_num, struct usdt_arg_spec *arg)

0 commit comments

Comments
 (0)