@@ -281,7 +281,21 @@ typedef class _bpf_assembler
281
281
inst.opcode = EBPF_OP_EXIT;
282
282
} else if (mnemonic == " call" ) {
283
283
inst.opcode = EBPF_OP_CALL;
284
- inst.imm = _decode_imm32 (operands[0 ]);
284
+ auto mode = operands[0 ];
285
+ auto target = operands[1 ];
286
+ // Mode determines if this is a helper function, a local call, or a call to a runtime function.
287
+ if (mode == " helper" ) {
288
+ inst.imm = _decode_imm32 (target);
289
+ inst.src = 0 ;
290
+ } else if (mode == " local" ) {
291
+ inst.imm == _decode_jump_target (target);
292
+ inst.src = 1 ;
293
+ } else if (mode == " runtime" ) {
294
+ inst.imm = _decode_imm32 (target);
295
+ inst.src = 2 ;
296
+ } else {
297
+ throw std::runtime_error (" Invalid call mode" );
298
+ }
285
299
} else {
286
300
mnemonic.ends_with (" 32" ) ? inst.opcode = EBPF_CLS_JMP32 : inst.opcode |= EBPF_CLS_JMP;
287
301
auto iter =
@@ -408,7 +422,7 @@ typedef class _bpf_assembler
408
422
{" and" , {&_bpf_assembler::_encode_alu, 2 }}, {" and32" , {&_bpf_assembler::_encode_alu, 2 }},
409
423
{" arsh" , {&_bpf_assembler::_encode_alu, 2 }}, {" arsh32" , {&_bpf_assembler::_encode_alu, 2 }},
410
424
{" be16" , {&_bpf_assembler::_encode_alu, 1 }}, {" be32" , {&_bpf_assembler::_encode_alu, 1 }},
411
- {" be64" , {&_bpf_assembler::_encode_alu, 1 }}, {" call" , {&_bpf_assembler::_encode_jmp, 1 }},
425
+ {" be64" , {&_bpf_assembler::_encode_alu, 1 }}, {" call" , {&_bpf_assembler::_encode_jmp, 2 }},
412
426
{" div" , {&_bpf_assembler::_encode_alu, 2 }}, {" div32" , {&_bpf_assembler::_encode_alu, 2 }},
413
427
{" exit" , {&_bpf_assembler::_encode_jmp, 0 }}, {" ja" , {&_bpf_assembler::_encode_jmp, 1 }},
414
428
{" jeq" , {&_bpf_assembler::_encode_jmp, 3 }}, {" jeq32" , {&_bpf_assembler::_encode_jmp, 3 }},
@@ -506,6 +520,14 @@ typedef class _bpf_assembler
506
520
507
521
bpf_encode_t encode = nullptr ;
508
522
size_t operand_count = 0 ;
523
+
524
+ // If this is a call instruction and it doesn't specify a mode, add the default mode (helper).
525
+ if (mnemonic == " call" ) {
526
+ if (operands.size () == 1 ) {
527
+ operands.insert (operands.begin (), " helper" );
528
+ }
529
+ }
530
+
509
531
if (mnemonic == " lock" ) {
510
532
// Find the handler for this atomic operation.
511
533
if (operands.size () == 0 ) {
@@ -557,7 +579,11 @@ typedef class _bpf_assembler
557
579
if (iter == _labels.end ()) {
558
580
throw std::runtime_error (std::string (" Invalid label: " ) + _jump_instructions[i].value ());
559
581
}
560
- output[i].offset = static_cast <uint16_t >(iter->second - i - 1 );
582
+ if (output[i].opcode == EBPF_OP_CALL) {
583
+ output[i].imm = static_cast <uint16_t >(iter->second - i - 1 );
584
+ } else {
585
+ output[i].offset = static_cast <uint16_t >(iter->second - i - 1 );
586
+ }
561
587
}
562
588
return output;
563
589
}
0 commit comments