@@ -200,12 +200,15 @@ enum usdt_arg_type {
200200 USDT_ARG_CONST ,
201201 USDT_ARG_REG ,
202202 USDT_ARG_REG_DEREF ,
203+ USDT_ARG_SIB ,
203204};
204205
205206/* should match exactly struct __bpf_usdt_arg_spec from usdt.bpf.h */
206207struct usdt_arg_spec {
207208 __u64 val_off ;
208- enum usdt_arg_type arg_type ;
209+ __u8 arg_type ; /* enum value stored as u8 */
210+ __u16 idx_packed ; /* [15:4]=idx_reg_off, [3:0]=scale_shift */
211+ __u8 reserved ; /* keep reg_off offset stable */
209212 short reg_off ;
210213 bool arg_signed ;
211214 char arg_bitshift ;
@@ -214,6 +217,10 @@ struct usdt_arg_spec {
214217/* should match BPF_USDT_MAX_ARG_CNT in usdt.bpf.h */
215218#define USDT_MAX_ARG_CNT 12
216219
220+ /* Helpers to (un)pack SIB extras from idx_packed without relying on bitfields. */
221+ #define BPF_USDT_IDX_PACK (idx_off , scale_shift ) \
222+ ((__u16)(((__u16)((idx_off) & 0x0fff)) << 4) | (__u16)((scale_shift) & 0x000f))
223+
217224/* should match struct __bpf_usdt_spec from usdt.bpf.h */
218225struct usdt_spec {
219226 struct usdt_arg_spec args [USDT_MAX_ARG_CNT ];
@@ -1283,11 +1290,54 @@ static int calc_pt_regs_off(const char *reg_name)
12831290
12841291static int parse_usdt_arg (const char * arg_str , int arg_num , struct usdt_arg_spec * arg , int * arg_sz )
12851292{
1286- char reg_name [16 ];
1287- int len , reg_off ;
1288- long off ;
1293+ char reg_name [16 ] = {0 }, idx_reg_name [16 ] = {0 };
1294+ int len , reg_off , idx_reg_off , scale = 1 ;
1295+ long off = 0 ;
1296+ __u16 scale_shift ;
1297+
1298+ if (sscanf (arg_str , " %d @ %ld ( %%%15[^,] , %%%15[^,] , %d ) %n" ,
1299+ arg_sz , & off , reg_name , idx_reg_name , & scale , & len ) == 5 ||
1300+ sscanf (arg_str , " %d @ ( %%%15[^,] , %%%15[^,] , %d ) %n" ,
1301+ arg_sz , reg_name , idx_reg_name , & scale , & len ) == 4 ||
1302+ sscanf (arg_str , " %d @ %ld ( %%%15[^,] , %%%15[^)] ) %n" ,
1303+ arg_sz , & off , reg_name , idx_reg_name , & len ) == 4 ||
1304+ sscanf (arg_str , " %d @ ( %%%15[^,] , %%%15[^)] ) %n" ,
1305+ arg_sz , reg_name , idx_reg_name , & len ) == 3
1306+ ) {
1307+ /*
1308+ * Scale Index Base case:
1309+ * 1@-96(%rbp,%rax,8)
1310+ * 1@(%rbp,%rax,8)
1311+ * 1@-96(%rbp,%rax)
1312+ * 1@(%rbp,%rax)
1313+ */
1314+ arg -> arg_type = USDT_ARG_SIB ;
1315+ arg -> val_off = off ;
12891316
1290- if (sscanf (arg_str , " %d @ %ld ( %%%15[^)] ) %n" , arg_sz , & off , reg_name , & len ) == 3 ) {
1317+ reg_off = calc_pt_regs_off (reg_name );
1318+ if (reg_off < 0 )
1319+ return reg_off ;
1320+ arg -> reg_off = reg_off ;
1321+
1322+ idx_reg_off = calc_pt_regs_off (idx_reg_name );
1323+ if (idx_reg_off < 0 )
1324+ return idx_reg_off ;
1325+ /* pack idx_reg_off and scale shift (scale in {1,2,4,8}) */
1326+ if (scale == 1 )
1327+ scale_shift = 0 ;
1328+ else if (scale == 2 )
1329+ scale_shift = 1 ;
1330+ else if (scale == 4 )
1331+ scale_shift = 2 ;
1332+ else if (scale == 8 )
1333+ scale_shift = 3 ;
1334+ else {
1335+ pr_warn ("usdt: invalid SIB scale %d, expected 1,2,4,8; defaulting to 1\n" , scale );
1336+ return - EINVAL ;
1337+ }
1338+ arg -> idx_packed = BPF_USDT_IDX_PACK (idx_reg_off , scale_shift );
1339+ } else if (sscanf (arg_str , " %d @ %ld ( %%%15[^)] ) %n" ,
1340+ arg_sz , & off , reg_name , & len ) == 3 ) {
12911341 /* Memory dereference case, e.g., -4@-20(%rbp) */
12921342 arg -> arg_type = USDT_ARG_REG_DEREF ;
12931343 arg -> val_off = off ;
@@ -1306,6 +1356,7 @@ static int parse_usdt_arg(const char *arg_str, int arg_num, struct usdt_arg_spec
13061356 } else if (sscanf (arg_str , " %d @ %%%15s %n" , arg_sz , reg_name , & len ) == 2 ) {
13071357 /* Register read case, e.g., -4@%eax */
13081358 arg -> arg_type = USDT_ARG_REG ;
1359+ /* register read has no memory offset */
13091360 arg -> val_off = 0 ;
13101361
13111362 reg_off = calc_pt_regs_off (reg_name );
0 commit comments