@@ -35,17 +35,39 @@ type Instruction struct {
35
35
Offset int16
36
36
Constant int64
37
37
38
- // Reference denotes a reference (e.g. a jump) to another symbol.
39
- Reference string
38
+ // Metadata contains optional metadata about this instruction
39
+ metadata * metadata
40
+ }
41
+
42
+ // WithSymbol marks the Instruction as a Symbol, which other Instructions
43
+ // can point to using corresponding calls to WithReference.
44
+ func (ins Instruction ) WithSymbol (name string ) Instruction {
45
+ if (ins .metadata != nil && ins .metadata .symbol == name ) ||
46
+ (ins .metadata == nil && name == "" ) {
47
+ return ins
48
+ }
40
49
41
- // Symbol denotes an instruction at the start of a function body.
42
- Symbol string
50
+ ins .metadata = ins .metadata .copy ()
51
+ ins .metadata .symbol = name
52
+ return ins
43
53
}
44
54
45
55
// Sym creates a symbol.
56
+ //
57
+ // Deprecated: use WithSymbol instead.
46
58
func (ins Instruction ) Sym (name string ) Instruction {
47
- ins .Symbol = name
48
- return ins
59
+ return ins .WithSymbol (name )
60
+ }
61
+
62
+ // Symbol returns the value ins has been marked with using WithSymbol,
63
+ // otherwise returns an empty string. A symbol is often an Instruction
64
+ // at the start of a function body.
65
+ func (ins Instruction ) Symbol () string {
66
+ if ins .metadata == nil {
67
+ return ""
68
+ }
69
+
70
+ return ins .metadata .symbol
49
71
}
50
72
51
73
// Unmarshal decodes a BPF instruction.
@@ -299,16 +321,63 @@ func (ins Instruction) Format(f fmt.State, c rune) {
299
321
}
300
322
301
323
ref:
302
- if ins .Reference != "" {
303
- fmt .Fprintf (f , " <%s>" , ins .Reference )
324
+ if ins .Reference () != "" {
325
+ fmt .Fprintf (f , " <%s>" , ins .Reference () )
304
326
}
305
327
}
306
328
329
+ func (ins Instruction ) equal (other Instruction ) bool {
330
+ return ins .OpCode == other .OpCode &&
331
+ ins .Dst == other .Dst &&
332
+ ins .Src == other .Src &&
333
+ ins .Offset == other .Offset &&
334
+ ins .Constant == other .Constant
335
+ }
336
+
307
337
// Size returns the amount of bytes ins would occupy in binary form.
308
338
func (ins Instruction ) Size () uint64 {
309
339
return uint64 (InstructionSize * ins .OpCode .rawInstructions ())
310
340
}
311
341
342
+ // WithReference makes ins reference another Symbol or map by name.
343
+ func (ins Instruction ) WithReference (ref string ) Instruction {
344
+ if (ins .metadata != nil && ins .metadata .reference == ref ) ||
345
+ (ins .metadata == nil && ref == "" ) {
346
+ return ins
347
+ }
348
+
349
+ ins .metadata = ins .metadata .copy ()
350
+ ins .metadata .reference = ref
351
+ return ins
352
+ }
353
+
354
+ // Reference returns the Symbol or map name referenced by ins, if any.
355
+ func (ins Instruction ) Reference () string {
356
+ if ins .metadata == nil {
357
+ return ""
358
+ }
359
+
360
+ return ins .metadata .reference
361
+ }
362
+
363
+ // metadata holds metadata about an Instruction.
364
+ type metadata struct {
365
+ // reference denotes a reference (e.g. a jump) to another symbol.
366
+ reference string
367
+ // symbol denotes an instruction at the start of a function body.
368
+ symbol string
369
+ }
370
+
371
+ // copy returns a copy of metadata.
372
+ // Always returns a valid pointer, even when called on a nil metadata.
373
+ func (m * metadata ) copy () * metadata {
374
+ var copy metadata
375
+ if m != nil {
376
+ copy = * m
377
+ }
378
+ return & copy
379
+ }
380
+
312
381
// Instructions is an eBPF program.
313
382
type Instructions []Instruction
314
383
@@ -342,7 +411,7 @@ func (insns Instructions) Name() string {
342
411
if len (insns ) == 0 {
343
412
return ""
344
413
}
345
- return insns [0 ].Symbol
414
+ return insns [0 ].Symbol ()
346
415
}
347
416
348
417
func (insns Instructions ) String () string {
@@ -369,7 +438,7 @@ func (insns Instructions) RewriteMapPtr(symbol string, fd int) error {
369
438
found := false
370
439
for i := range insns {
371
440
ins := & insns [i ]
372
- if ins .Reference != symbol {
441
+ if ins .Reference () != symbol {
373
442
continue
374
443
}
375
444
@@ -393,15 +462,15 @@ func (insns Instructions) SymbolOffsets() (map[string]int, error) {
393
462
offsets := make (map [string ]int )
394
463
395
464
for i , ins := range insns {
396
- if ins .Symbol == "" {
465
+ if ins .Symbol () == "" {
397
466
continue
398
467
}
399
468
400
- if _ , ok := offsets [ins .Symbol ]; ok {
401
- return nil , fmt .Errorf ("duplicate symbol %s" , ins .Symbol )
469
+ if _ , ok := offsets [ins .Symbol () ]; ok {
470
+ return nil , fmt .Errorf ("duplicate symbol %s" , ins .Symbol () )
402
471
}
403
472
404
- offsets [ins .Symbol ] = i
473
+ offsets [ins .Symbol () ] = i
405
474
}
406
475
407
476
return offsets , nil
@@ -418,15 +487,15 @@ func (insns Instructions) FunctionReferences() map[string]bool {
418
487
continue
419
488
}
420
489
421
- if ins .Reference == "" {
490
+ if ins .Reference () == "" {
422
491
continue
423
492
}
424
493
425
494
if ! ins .IsFunctionReference () {
426
495
continue
427
496
}
428
497
429
- calls [ins .Reference ] = true
498
+ calls [ins .Reference () ] = true
430
499
}
431
500
432
501
return calls
@@ -438,11 +507,11 @@ func (insns Instructions) ReferenceOffsets() map[string][]int {
438
507
offsets := make (map [string ][]int )
439
508
440
509
for i , ins := range insns {
441
- if ins .Reference == "" {
510
+ if ins .Reference () == "" {
442
511
continue
443
512
}
444
513
445
- offsets [ins .Reference ] = append (offsets [ins .Reference ], i )
514
+ offsets [ins .Reference () ] = append (offsets [ins .Reference () ], i )
446
515
}
447
516
448
517
return offsets
@@ -493,8 +562,8 @@ func (insns Instructions) Format(f fmt.State, c rune) {
493
562
494
563
iter := insns .Iterate ()
495
564
for iter .Next () {
496
- if iter .Ins .Symbol != "" {
497
- fmt .Fprintf (f , "%s%s:\n " , symIndent , iter .Ins .Symbol )
565
+ if iter .Ins .Symbol () != "" {
566
+ fmt .Fprintf (f , "%s%s:\n " , symIndent , iter .Ins .Symbol () )
498
567
}
499
568
fmt .Fprintf (f , "%s%*d: %v\n " , indent , offsetWidth , iter .Offset , iter .Ins )
500
569
}
@@ -552,15 +621,15 @@ func (insns Instructions) resolveFunctionReferences() error {
552
621
for iter .Next () {
553
622
ins := iter .Ins
554
623
555
- if ins .Symbol == "" {
624
+ if ins .Symbol () == "" {
556
625
continue
557
626
}
558
627
559
- if _ , ok := symbolOffsets [ins .Symbol ]; ok {
560
- return fmt .Errorf ("duplicate symbol %s" , ins .Symbol )
628
+ if _ , ok := symbolOffsets [ins .Symbol () ]; ok {
629
+ return fmt .Errorf ("duplicate symbol %s" , ins .Symbol () )
561
630
}
562
631
563
- symbolOffsets [ins .Symbol ] = iter .Offset
632
+ symbolOffsets [ins .Symbol () ] = iter .Offset
564
633
}
565
634
566
635
// Find all instructions tagged as references to other symbols.
@@ -572,23 +641,23 @@ func (insns Instructions) resolveFunctionReferences() error {
572
641
offset := iter .Offset
573
642
ins := iter .Ins
574
643
575
- if ins .Reference == "" {
644
+ if ins .Reference () == "" {
576
645
continue
577
646
}
578
647
579
648
switch {
580
649
case ins .IsFunctionReference () && ins .Constant == - 1 :
581
- symOffset , ok := symbolOffsets [ins .Reference ]
650
+ symOffset , ok := symbolOffsets [ins .Reference () ]
582
651
if ! ok {
583
- return fmt .Errorf ("%s at insn %d: symbol %q: %w" , ins .OpCode , i , ins .Reference , ErrUnsatisfiedProgramReference )
652
+ return fmt .Errorf ("%s at insn %d: symbol %q: %w" , ins .OpCode , i , ins .Reference () , ErrUnsatisfiedProgramReference )
584
653
}
585
654
586
655
ins .Constant = int64 (symOffset - offset - 1 )
587
656
588
657
case ins .OpCode .Class ().IsJump () && ins .Offset == - 1 :
589
- symOffset , ok := symbolOffsets [ins .Reference ]
658
+ symOffset , ok := symbolOffsets [ins .Reference () ]
590
659
if ! ok {
591
- return fmt .Errorf ("%s at insn %d: symbol %q: %w" , ins .OpCode , i , ins .Reference , ErrUnsatisfiedProgramReference )
660
+ return fmt .Errorf ("%s at insn %d: symbol %q: %w" , ins .OpCode , i , ins .Reference () , ErrUnsatisfiedProgramReference )
592
661
}
593
662
594
663
ins .Offset = int16 (symOffset - offset - 1 )
0 commit comments