@@ -200,12 +200,15 @@ enum usdt_arg_type {
200
200
USDT_ARG_CONST ,
201
201
USDT_ARG_REG ,
202
202
USDT_ARG_REG_DEREF ,
203
+ USDT_ARG_SIB ,
203
204
};
204
205
205
206
/* should match exactly struct __bpf_usdt_arg_spec from usdt.bpf.h */
206
207
struct usdt_arg_spec {
207
208
__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 */
209
212
short reg_off ;
210
213
bool arg_signed ;
211
214
char arg_bitshift ;
@@ -214,6 +217,10 @@ struct usdt_arg_spec {
214
217
/* should match BPF_USDT_MAX_ARG_CNT in usdt.bpf.h */
215
218
#define USDT_MAX_ARG_CNT 12
216
219
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
+
217
224
/* should match struct __bpf_usdt_spec from usdt.bpf.h */
218
225
struct usdt_spec {
219
226
struct usdt_arg_spec args [USDT_MAX_ARG_CNT ];
@@ -1283,11 +1290,54 @@ static int calc_pt_regs_off(const char *reg_name)
1283
1290
1284
1291
static int parse_usdt_arg (const char * arg_str , int arg_num , struct usdt_arg_spec * arg , int * arg_sz )
1285
1292
{
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 ;
1289
1316
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 ) {
1291
1341
/* Memory dereference case, e.g., -4@-20(%rbp) */
1292
1342
arg -> arg_type = USDT_ARG_REG_DEREF ;
1293
1343
arg -> val_off = off ;
@@ -1306,6 +1356,7 @@ static int parse_usdt_arg(const char *arg_str, int arg_num, struct usdt_arg_spec
1306
1356
} else if (sscanf (arg_str , " %d @ %%%15s %n" , arg_sz , reg_name , & len ) == 2 ) {
1307
1357
/* Register read case, e.g., -4@%eax */
1308
1358
arg -> arg_type = USDT_ARG_REG ;
1359
+ /* register read has no memory offset */
1309
1360
arg -> val_off = 0 ;
1310
1361
1311
1362
reg_off = calc_pt_regs_off (reg_name );
0 commit comments