github.com/cilium/ebpf@v0.15.1-0.20240517100537-8079b37aa138/internal/auxv_test.go (about) 1 package internal 2 3 import ( 4 "encoding/binary" 5 "errors" 6 "fmt" 7 "os" 8 "testing" 9 "unsafe" 10 11 "github.com/cilium/ebpf/internal/unix" 12 ) 13 14 type auxvFileReader struct { 15 file *os.File 16 order binary.ByteOrder 17 uintptrIs32bits bool 18 } 19 20 func (r *auxvFileReader) Close() error { 21 return r.file.Close() 22 } 23 24 type auxvPair32 struct { 25 Tag, Value uint32 26 } 27 28 type auxvPair64 struct { 29 Tag, Value uint64 30 } 31 32 func (r *auxvFileReader) ReadAuxvPair() (tag, value uint64, _ error) { 33 if r.uintptrIs32bits { 34 var aux auxvPair32 35 if err := binary.Read(r.file, r.order, &aux); err != nil { 36 return 0, 0, fmt.Errorf("reading auxv entry: %w", err) 37 } 38 return uint64(aux.Tag), uint64(aux.Value), nil 39 } 40 41 var aux auxvPair64 42 if err := binary.Read(r.file, r.order, &aux); err != nil { 43 return 0, 0, fmt.Errorf("reading auxv entry: %w", err) 44 } 45 return aux.Tag, aux.Value, nil 46 } 47 48 func newAuxFileReader(path string, order binary.ByteOrder, uintptrIs32bits bool) (auxvPairReader, error) { 49 // Read data from the auxiliary vector, which is normally passed directly 50 // to the process. Go does not expose that data before go 1.21, so we must read it from procfs. 51 // https://man7.org/linux/man-pages/man3/getauxval.3.html 52 av, err := os.Open(path) 53 if errors.Is(err, unix.EACCES) { 54 return nil, fmt.Errorf("opening auxv: %w (process may not be dumpable due to file capabilities)", err) 55 } 56 if err != nil { 57 return nil, fmt.Errorf("opening auxv: %w", err) 58 } 59 60 return &auxvFileReader{ 61 file: av, 62 order: order, 63 uintptrIs32bits: uintptrIs32bits, 64 }, nil 65 } 66 67 func newDefaultAuxvFileReader() (auxvPairReader, error) { 68 const uintptrIs32bits = unsafe.Sizeof((uintptr)(0)) == 4 69 return newAuxFileReader("/proc/self/auxv", NativeEndian, uintptrIs32bits) 70 } 71 72 func TestAuxvBothSourcesEqual(t *testing.T) { 73 runtimeBased, err := newAuxvRuntimeReader() 74 if err != nil { 75 t.Fatal(err) 76 } 77 fileBased, err := newDefaultAuxvFileReader() 78 if err != nil { 79 t.Fatal(err) 80 } 81 82 for { 83 runtimeTag, runtimeValue, err := runtimeBased.ReadAuxvPair() 84 if err != nil { 85 t.Fatal(err) 86 } 87 88 fileTag, fileValue, err := fileBased.ReadAuxvPair() 89 if err != nil { 90 t.Fatal(err) 91 } 92 93 if runtimeTag != fileTag { 94 t.Errorf("mismatching tags: runtime=%v, file=%v", runtimeTag, fileTag) 95 } 96 97 if runtimeValue != fileValue { 98 t.Errorf("mismatching values: runtime=%v, file=%v", runtimeValue, fileValue) 99 } 100 101 if runtimeTag == _AT_NULL { 102 break 103 } 104 } 105 }