@@ -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
11461146static 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