Skip to content

Commit d1d51a6

Browse files
committed
Merge branch 'libbpf: usdt arm arg parsing support'
Puranjay Mohan says: ==================== This series add the support of the ARM architecture to libbpf USDT. This involves implementing the parse_usdt_arg() function for ARM. It was seen that the last part of parse_usdt_arg() is repeated for all architectures, so, the first patch in this series refactors these functions and moved the post processing to parse_usdt_spec() Changes in V2[1] to V3: - Use a tabular approach to find register offsets. - Add the patch for refactoring parse_usdt_arg() ==================== Signed-off-by: Andrii Nakryiko <andrii@kernel.org>
2 parents 3ecde21 + 720d93b commit d1d51a6

File tree

1 file changed

+118
-78
lines changed

1 file changed

+118
-78
lines changed

tools/lib/bpf/usdt.c

Lines changed: 118 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -1141,12 +1141,13 @@ static int parse_usdt_note(Elf *elf, const char *path, GElf_Nhdr *nhdr,
11411141
return 0;
11421142
}
11431143

1144-
static int parse_usdt_arg(const char *arg_str, int arg_num, struct usdt_arg_spec *arg);
1144+
static int parse_usdt_arg(const char *arg_str, int arg_num, struct usdt_arg_spec *arg, int *arg_sz);
11451145

11461146
static int parse_usdt_spec(struct usdt_spec *spec, const struct usdt_note *note, __u64 usdt_cookie)
11471147
{
1148+
struct usdt_arg_spec *arg;
11481149
const char *s;
1149-
int len;
1150+
int arg_sz, len;
11501151

11511152
spec->usdt_cookie = usdt_cookie;
11521153
spec->arg_cnt = 0;
@@ -1159,10 +1160,25 @@ static int parse_usdt_spec(struct usdt_spec *spec, const struct usdt_note *note,
11591160
return -E2BIG;
11601161
}
11611162

1162-
len = parse_usdt_arg(s, spec->arg_cnt, &spec->args[spec->arg_cnt]);
1163+
arg = &spec->args[spec->arg_cnt];
1164+
len = parse_usdt_arg(s, spec->arg_cnt, arg, &arg_sz);
11631165
if (len < 0)
11641166
return len;
11651167

1168+
arg->arg_signed = arg_sz < 0;
1169+
if (arg_sz < 0)
1170+
arg_sz = -arg_sz;
1171+
1172+
switch (arg_sz) {
1173+
case 1: case 2: case 4: case 8:
1174+
arg->arg_bitshift = 64 - arg_sz * 8;
1175+
break;
1176+
default:
1177+
pr_warn("usdt: unsupported arg #%d (spec '%s') size: %d\n",
1178+
spec->arg_cnt, s, arg_sz);
1179+
return -EINVAL;
1180+
}
1181+
11661182
s += len;
11671183
spec->arg_cnt++;
11681184
}
@@ -1219,29 +1235,29 @@ static int calc_pt_regs_off(const char *reg_name)
12191235
return -ENOENT;
12201236
}
12211237

1222-
static int parse_usdt_arg(const char *arg_str, int arg_num, struct usdt_arg_spec *arg)
1238+
static int parse_usdt_arg(const char *arg_str, int arg_num, struct usdt_arg_spec *arg, int *arg_sz)
12231239
{
12241240
char reg_name[16];
1225-
int arg_sz, len, reg_off;
1241+
int len, reg_off;
12261242
long off;
12271243

1228-
if (sscanf(arg_str, " %d @ %ld ( %%%15[^)] ) %n", &arg_sz, &off, reg_name, &len) == 3) {
1244+
if (sscanf(arg_str, " %d @ %ld ( %%%15[^)] ) %n", arg_sz, &off, reg_name, &len) == 3) {
12291245
/* Memory dereference case, e.g., -4@-20(%rbp) */
12301246
arg->arg_type = USDT_ARG_REG_DEREF;
12311247
arg->val_off = off;
12321248
reg_off = calc_pt_regs_off(reg_name);
12331249
if (reg_off < 0)
12341250
return reg_off;
12351251
arg->reg_off = reg_off;
1236-
} else if (sscanf(arg_str, " %d @ ( %%%15[^)] ) %n", &arg_sz, reg_name, &len) == 2) {
1252+
} else if (sscanf(arg_str, " %d @ ( %%%15[^)] ) %n", arg_sz, reg_name, &len) == 2) {
12371253
/* Memory dereference case without offset, e.g., 8@(%rsp) */
12381254
arg->arg_type = USDT_ARG_REG_DEREF;
12391255
arg->val_off = 0;
12401256
reg_off = calc_pt_regs_off(reg_name);
12411257
if (reg_off < 0)
12421258
return reg_off;
12431259
arg->reg_off = reg_off;
1244-
} else if (sscanf(arg_str, " %d @ %%%15s %n", &arg_sz, reg_name, &len) == 2) {
1260+
} else if (sscanf(arg_str, " %d @ %%%15s %n", arg_sz, reg_name, &len) == 2) {
12451261
/* Register read case, e.g., -4@%eax */
12461262
arg->arg_type = USDT_ARG_REG;
12471263
arg->val_off = 0;
@@ -1250,7 +1266,7 @@ static int parse_usdt_arg(const char *arg_str, int arg_num, struct usdt_arg_spec
12501266
if (reg_off < 0)
12511267
return reg_off;
12521268
arg->reg_off = reg_off;
1253-
} else if (sscanf(arg_str, " %d @ $%ld %n", &arg_sz, &off, &len) == 2) {
1269+
} else if (sscanf(arg_str, " %d @ $%ld %n", arg_sz, &off, &len) == 2) {
12541270
/* Constant value case, e.g., 4@$71 */
12551271
arg->arg_type = USDT_ARG_CONST;
12561272
arg->val_off = off;
@@ -1260,34 +1276,20 @@ static int parse_usdt_arg(const char *arg_str, int arg_num, struct usdt_arg_spec
12601276
return -EINVAL;
12611277
}
12621278

1263-
arg->arg_signed = arg_sz < 0;
1264-
if (arg_sz < 0)
1265-
arg_sz = -arg_sz;
1266-
1267-
switch (arg_sz) {
1268-
case 1: case 2: case 4: case 8:
1269-
arg->arg_bitshift = 64 - arg_sz * 8;
1270-
break;
1271-
default:
1272-
pr_warn("usdt: unsupported arg #%d (spec '%s') size: %d\n",
1273-
arg_num, arg_str, arg_sz);
1274-
return -EINVAL;
1275-
}
1276-
12771279
return len;
12781280
}
12791281

12801282
#elif defined(__s390x__)
12811283

12821284
/* Do not support __s390__ for now, since user_pt_regs is broken with -m31. */
12831285

1284-
static int parse_usdt_arg(const char *arg_str, int arg_num, struct usdt_arg_spec *arg)
1286+
static int parse_usdt_arg(const char *arg_str, int arg_num, struct usdt_arg_spec *arg, int *arg_sz)
12851287
{
12861288
unsigned int reg;
1287-
int arg_sz, len;
1289+
int len;
12881290
long off;
12891291

1290-
if (sscanf(arg_str, " %d @ %ld ( %%r%u ) %n", &arg_sz, &off, &reg, &len) == 3) {
1292+
if (sscanf(arg_str, " %d @ %ld ( %%r%u ) %n", arg_sz, &off, &reg, &len) == 3) {
12911293
/* Memory dereference case, e.g., -2@-28(%r15) */
12921294
arg->arg_type = USDT_ARG_REG_DEREF;
12931295
arg->val_off = off;
@@ -1296,7 +1298,7 @@ static int parse_usdt_arg(const char *arg_str, int arg_num, struct usdt_arg_spec
12961298
return -EINVAL;
12971299
}
12981300
arg->reg_off = offsetof(user_pt_regs, gprs[reg]);
1299-
} else if (sscanf(arg_str, " %d @ %%r%u %n", &arg_sz, &reg, &len) == 2) {
1301+
} else if (sscanf(arg_str, " %d @ %%r%u %n", arg_sz, &reg, &len) == 2) {
13001302
/* Register read case, e.g., -8@%r0 */
13011303
arg->arg_type = USDT_ARG_REG;
13021304
arg->val_off = 0;
@@ -1305,7 +1307,7 @@ static int parse_usdt_arg(const char *arg_str, int arg_num, struct usdt_arg_spec
13051307
return -EINVAL;
13061308
}
13071309
arg->reg_off = offsetof(user_pt_regs, gprs[reg]);
1308-
} else if (sscanf(arg_str, " %d @ %ld %n", &arg_sz, &off, &len) == 2) {
1310+
} else if (sscanf(arg_str, " %d @ %ld %n", arg_sz, &off, &len) == 2) {
13091311
/* Constant value case, e.g., 4@71 */
13101312
arg->arg_type = USDT_ARG_CONST;
13111313
arg->val_off = off;
@@ -1315,20 +1317,6 @@ static int parse_usdt_arg(const char *arg_str, int arg_num, struct usdt_arg_spec
13151317
return -EINVAL;
13161318
}
13171319

1318-
arg->arg_signed = arg_sz < 0;
1319-
if (arg_sz < 0)
1320-
arg_sz = -arg_sz;
1321-
1322-
switch (arg_sz) {
1323-
case 1: case 2: case 4: case 8:
1324-
arg->arg_bitshift = 64 - arg_sz * 8;
1325-
break;
1326-
default:
1327-
pr_warn("usdt: unsupported arg #%d (spec '%s') size: %d\n",
1328-
arg_num, arg_str, arg_sz);
1329-
return -EINVAL;
1330-
}
1331-
13321320
return len;
13331321
}
13341322

@@ -1348,34 +1336,34 @@ static int calc_pt_regs_off(const char *reg_name)
13481336
return -ENOENT;
13491337
}
13501338

1351-
static int parse_usdt_arg(const char *arg_str, int arg_num, struct usdt_arg_spec *arg)
1339+
static int parse_usdt_arg(const char *arg_str, int arg_num, struct usdt_arg_spec *arg, int *arg_sz)
13521340
{
13531341
char reg_name[16];
1354-
int arg_sz, len, reg_off;
1342+
int len, reg_off;
13551343
long off;
13561344

1357-
if (sscanf(arg_str, " %d @ \[ %15[a-z0-9], %ld ] %n", &arg_sz, reg_name, &off, &len) == 3) {
1345+
if (sscanf(arg_str, " %d @ \[ %15[a-z0-9] , %ld ] %n", arg_sz, reg_name, &off, &len) == 3) {
13581346
/* Memory dereference case, e.g., -4@[sp, 96] */
13591347
arg->arg_type = USDT_ARG_REG_DEREF;
13601348
arg->val_off = off;
13611349
reg_off = calc_pt_regs_off(reg_name);
13621350
if (reg_off < 0)
13631351
return reg_off;
13641352
arg->reg_off = reg_off;
1365-
} else if (sscanf(arg_str, " %d @ \[ %15[a-z0-9] ] %n", &arg_sz, reg_name, &len) == 2) {
1353+
} else if (sscanf(arg_str, " %d @ \[ %15[a-z0-9] ] %n", arg_sz, reg_name, &len) == 2) {
13661354
/* Memory dereference case, e.g., -4@[sp] */
13671355
arg->arg_type = USDT_ARG_REG_DEREF;
13681356
arg->val_off = 0;
13691357
reg_off = calc_pt_regs_off(reg_name);
13701358
if (reg_off < 0)
13711359
return reg_off;
13721360
arg->reg_off = reg_off;
1373-
} else if (sscanf(arg_str, " %d @ %ld %n", &arg_sz, &off, &len) == 2) {
1361+
} else if (sscanf(arg_str, " %d @ %ld %n", arg_sz, &off, &len) == 2) {
13741362
/* Constant value case, e.g., 4@5 */
13751363
arg->arg_type = USDT_ARG_CONST;
13761364
arg->val_off = off;
13771365
arg->reg_off = 0;
1378-
} else if (sscanf(arg_str, " %d @ %15[a-z0-9] %n", &arg_sz, reg_name, &len) == 2) {
1366+
} else if (sscanf(arg_str, " %d @ %15[a-z0-9] %n", arg_sz, reg_name, &len) == 2) {
13791367
/* Register read case, e.g., -8@x4 */
13801368
arg->arg_type = USDT_ARG_REG;
13811369
arg->val_off = 0;
@@ -1388,20 +1376,6 @@ static int parse_usdt_arg(const char *arg_str, int arg_num, struct usdt_arg_spec
13881376
return -EINVAL;
13891377
}
13901378

1391-
arg->arg_signed = arg_sz < 0;
1392-
if (arg_sz < 0)
1393-
arg_sz = -arg_sz;
1394-
1395-
switch (arg_sz) {
1396-
case 1: case 2: case 4: case 8:
1397-
arg->arg_bitshift = 64 - arg_sz * 8;
1398-
break;
1399-
default:
1400-
pr_warn("usdt: unsupported arg #%d (spec '%s') size: %d\n",
1401-
arg_num, arg_str, arg_sz);
1402-
return -EINVAL;
1403-
}
1404-
14051379
return len;
14061380
}
14071381

@@ -1456,26 +1430,26 @@ static int calc_pt_regs_off(const char *reg_name)
14561430
return -ENOENT;
14571431
}
14581432

1459-
static int parse_usdt_arg(const char *arg_str, int arg_num, struct usdt_arg_spec *arg)
1433+
static int parse_usdt_arg(const char *arg_str, int arg_num, struct usdt_arg_spec *arg, int *arg_sz)
14601434
{
14611435
char reg_name[16];
1462-
int arg_sz, len, reg_off;
1436+
int len, reg_off;
14631437
long off;
14641438

1465-
if (sscanf(arg_str, " %d @ %ld ( %15[a-z0-9] ) %n", &arg_sz, &off, reg_name, &len) == 3) {
1439+
if (sscanf(arg_str, " %d @ %ld ( %15[a-z0-9] ) %n", arg_sz, &off, reg_name, &len) == 3) {
14661440
/* Memory dereference case, e.g., -8@-88(s0) */
14671441
arg->arg_type = USDT_ARG_REG_DEREF;
14681442
arg->val_off = off;
14691443
reg_off = calc_pt_regs_off(reg_name);
14701444
if (reg_off < 0)
14711445
return reg_off;
14721446
arg->reg_off = reg_off;
1473-
} else if (sscanf(arg_str, " %d @ %ld %n", &arg_sz, &off, &len) == 2) {
1447+
} else if (sscanf(arg_str, " %d @ %ld %n", arg_sz, &off, &len) == 2) {
14741448
/* Constant value case, e.g., 4@5 */
14751449
arg->arg_type = USDT_ARG_CONST;
14761450
arg->val_off = off;
14771451
arg->reg_off = 0;
1478-
} else if (sscanf(arg_str, " %d @ %15[a-z0-9] %n", &arg_sz, reg_name, &len) == 2) {
1452+
} else if (sscanf(arg_str, " %d @ %15[a-z0-9] %n", arg_sz, reg_name, &len) == 2) {
14791453
/* Register read case, e.g., -8@a1 */
14801454
arg->arg_type = USDT_ARG_REG;
14811455
arg->val_off = 0;
@@ -1488,17 +1462,83 @@ static int parse_usdt_arg(const char *arg_str, int arg_num, struct usdt_arg_spec
14881462
return -EINVAL;
14891463
}
14901464

1491-
arg->arg_signed = arg_sz < 0;
1492-
if (arg_sz < 0)
1493-
arg_sz = -arg_sz;
1465+
return len;
1466+
}
14941467

1495-
switch (arg_sz) {
1496-
case 1: case 2: case 4: case 8:
1497-
arg->arg_bitshift = 64 - arg_sz * 8;
1498-
break;
1499-
default:
1500-
pr_warn("usdt: unsupported arg #%d (spec '%s') size: %d\n",
1501-
arg_num, arg_str, arg_sz);
1468+
#elif defined(__arm__)
1469+
1470+
static int calc_pt_regs_off(const char *reg_name)
1471+
{
1472+
static struct {
1473+
const char *name;
1474+
size_t pt_regs_off;
1475+
} reg_map[] = {
1476+
{ "r0", offsetof(struct pt_regs, uregs[0]) },
1477+
{ "r1", offsetof(struct pt_regs, uregs[1]) },
1478+
{ "r2", offsetof(struct pt_regs, uregs[2]) },
1479+
{ "r3", offsetof(struct pt_regs, uregs[3]) },
1480+
{ "r4", offsetof(struct pt_regs, uregs[4]) },
1481+
{ "r5", offsetof(struct pt_regs, uregs[5]) },
1482+
{ "r6", offsetof(struct pt_regs, uregs[6]) },
1483+
{ "r7", offsetof(struct pt_regs, uregs[7]) },
1484+
{ "r8", offsetof(struct pt_regs, uregs[8]) },
1485+
{ "r9", offsetof(struct pt_regs, uregs[9]) },
1486+
{ "r10", offsetof(struct pt_regs, uregs[10]) },
1487+
{ "fp", offsetof(struct pt_regs, uregs[11]) },
1488+
{ "ip", offsetof(struct pt_regs, uregs[12]) },
1489+
{ "sp", offsetof(struct pt_regs, uregs[13]) },
1490+
{ "lr", offsetof(struct pt_regs, uregs[14]) },
1491+
{ "pc", offsetof(struct pt_regs, uregs[15]) },
1492+
};
1493+
int i;
1494+
1495+
for (i = 0; i < ARRAY_SIZE(reg_map); i++) {
1496+
if (strcmp(reg_name, reg_map[i].name) == 0)
1497+
return reg_map[i].pt_regs_off;
1498+
}
1499+
1500+
pr_warn("usdt: unrecognized register '%s'\n", reg_name);
1501+
return -ENOENT;
1502+
}
1503+
1504+
static int parse_usdt_arg(const char *arg_str, int arg_num, struct usdt_arg_spec *arg, int *arg_sz)
1505+
{
1506+
char reg_name[16];
1507+
int len, reg_off;
1508+
long off;
1509+
1510+
if (sscanf(arg_str, " %d @ \[ %15[a-z0-9] , #%ld ] %n",
1511+
arg_sz, reg_name, &off, &len) == 3) {
1512+
/* Memory dereference case, e.g., -4@[fp, #96] */
1513+
arg->arg_type = USDT_ARG_REG_DEREF;
1514+
arg->val_off = off;
1515+
reg_off = calc_pt_regs_off(reg_name);
1516+
if (reg_off < 0)
1517+
return reg_off;
1518+
arg->reg_off = reg_off;
1519+
} else if (sscanf(arg_str, " %d @ \[ %15[a-z0-9] ] %n", arg_sz, reg_name, &len) == 2) {
1520+
/* Memory dereference case, e.g., -4@[sp] */
1521+
arg->arg_type = USDT_ARG_REG_DEREF;
1522+
arg->val_off = 0;
1523+
reg_off = calc_pt_regs_off(reg_name);
1524+
if (reg_off < 0)
1525+
return reg_off;
1526+
arg->reg_off = reg_off;
1527+
} else if (sscanf(arg_str, " %d @ #%ld %n", arg_sz, &off, &len) == 2) {
1528+
/* Constant value case, e.g., 4@#5 */
1529+
arg->arg_type = USDT_ARG_CONST;
1530+
arg->val_off = off;
1531+
arg->reg_off = 0;
1532+
} else if (sscanf(arg_str, " %d @ %15[a-z0-9] %n", arg_sz, reg_name, &len) == 2) {
1533+
/* Register read case, e.g., -8@r4 */
1534+
arg->arg_type = USDT_ARG_REG;
1535+
arg->val_off = 0;
1536+
reg_off = calc_pt_regs_off(reg_name);
1537+
if (reg_off < 0)
1538+
return reg_off;
1539+
arg->reg_off = reg_off;
1540+
} else {
1541+
pr_warn("usdt: unrecognized arg #%d spec '%s'\n", arg_num, arg_str);
15021542
return -EINVAL;
15031543
}
15041544

@@ -1507,7 +1547,7 @@ static int parse_usdt_arg(const char *arg_str, int arg_num, struct usdt_arg_spec
15071547

15081548
#else
15091549

1510-
static int parse_usdt_arg(const char *arg_str, int arg_num, struct usdt_arg_spec *arg)
1550+
static int parse_usdt_arg(const char *arg_str, int arg_num, struct usdt_arg_spec *arg, int *arg_sz)
15111551
{
15121552
pr_warn("usdt: libbpf doesn't support USDTs on current architecture\n");
15131553
return -ENOTSUP;

0 commit comments

Comments
 (0)