-
Notifications
You must be signed in to change notification settings - Fork 678
Commit
Extract auxv related code to own file, and use runtime provided auxv fetching function starting from go 1.21. The old file based code is kept for old go version and tests. Signed-off-by: Paul Cacheux <paul.cacheux@datadoghq.com>
- Loading branch information
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
package internal | ||
|
||
import ( | ||
"encoding/binary" | ||
"errors" | ||
"fmt" | ||
"os" | ||
|
||
"github.com/cilium/ebpf/internal/unix" | ||
) | ||
|
||
type auxvPairReader interface { | ||
Close() error | ||
ReadAuxvPair() (uint64, uint64, error) | ||
} | ||
|
||
type auxvFileReader struct { | ||
file *os.File | ||
order binary.ByteOrder | ||
uintptrIs32bits bool | ||
} | ||
|
||
func (r *auxvFileReader) Close() error { | ||
return r.file.Close() | ||
} | ||
|
||
type auxvPair32 struct { | ||
Tag, Value uint32 | ||
} | ||
|
||
type auxvPair64 struct { | ||
Tag, Value uint64 | ||
} | ||
|
||
func (r *auxvFileReader) ReadAuxvPair() (tag, value uint64, _ error) { | ||
if r.uintptrIs32bits { | ||
var aux auxvPair32 | ||
if err := binary.Read(r.file, r.order, &aux); err != nil { | ||
return 0, 0, fmt.Errorf("reading auxv entry: %w", err) | ||
} | ||
return uint64(aux.Tag), uint64(aux.Value), nil | ||
} | ||
|
||
var aux auxvPair64 | ||
if err := binary.Read(r.file, r.order, &aux); err != nil { | ||
return 0, 0, fmt.Errorf("reading auxv entry: %w", err) | ||
} | ||
return aux.Tag, aux.Value, nil | ||
} | ||
|
||
func newAuxFileReader(path string, order binary.ByteOrder, uintptrIs32bits bool) (auxvPairReader, error) { | ||
// Read data from the auxiliary vector, which is normally passed directly | ||
// to the process. Go does not expose that data before go 1.21, so we must read it from procfs. | ||
// https://man7.org/linux/man-pages/man3/getauxval.3.html | ||
av, err := os.Open(path) | ||
if errors.Is(err, unix.EACCES) { | ||
return nil, fmt.Errorf("opening auxv: %w (process may not be dumpable due to file capabilities)", err) | ||
} | ||
if err != nil { | ||
return nil, fmt.Errorf("opening auxv: %w", err) | ||
} | ||
|
||
return &auxvFileReader{ | ||
file: av, | ||
order: order, | ||
uintptrIs32bits: uintptrIs32bits, | ||
}, nil | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
//go:build go1.21 | ||
|
||
package internal | ||
|
||
import ( | ||
"errors" | ||
"io" | ||
_ "unsafe" // for linkname | ||
) | ||
|
||
//go:linkname runtime_getAuxv runtime.getAuxv | ||
func runtime_getAuxv() []uintptr | ||
|
||
type auxvRuntimeReader struct { | ||
data []uintptr | ||
index int | ||
} | ||
|
||
func (r *auxvRuntimeReader) Close() error { | ||
return nil | ||
} | ||
|
||
func (r *auxvRuntimeReader) ReadAuxvPair() (uint64, uint64, error) { | ||
if r.index+1 >= len(r.data) { | ||
return 0, 0, io.EOF | ||
} | ||
|
||
tag, value := r.data[r.index], r.data[r.index+1] | ||
r.index += 2 | ||
return uint64(tag), uint64(value), nil | ||
} | ||
|
||
func auxvReader() (auxvPairReader, error) { | ||
data := runtime_getAuxv() | ||
|
||
if len(data)%2 != 0 { | ||
return nil, errors.New("malformed auxv passed from runtime") | ||
} | ||
|
||
return &auxvRuntimeReader{ | ||
data: data, | ||
index: 0, | ||
}, nil | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
//go:build !go1.21 | ||
|
||
package internal | ||
|
||
import ( | ||
"encoding/binary" | ||
"unsafe" | ||
) | ||
|
||
func auxvReader() (auxvPairReader, error) { | ||
const uintptrIs32bits = unsafe.Sizeof((uintptr)(0)) == 4 | ||
return newAuxFileReaderFromPath("/proc/self/auxv", binary.NativeEndian, uintptrIs32bits) | ||
Check failure on line 12 in internal/auxv_pre_go121.go GitHub Actions / Run tests on arm64
Check failure on line 12 in internal/auxv_pre_go121.go GitHub Actions / Run tests on arm64
Check failure on line 12 in internal/auxv_pre_go121.go GitHub Actions / Run tests on arm64
Check failure on line 12 in internal/auxv_pre_go121.go GitHub Actions / Run tests on arm64
Check failure on line 12 in internal/auxv_pre_go121.go GitHub Actions / Run tests on previous stable Go
Check failure on line 12 in internal/auxv_pre_go121.go GitHub Actions / Run tests on previous stable Go
Check failure on line 12 in internal/auxv_pre_go121.go GitHub Actions / Run tests on previous stable Go
Check failure on line 12 in internal/auxv_pre_go121.go GitHub Actions / Run tests on previous stable Go
Check failure on line 12 in internal/auxv_pre_go121.go GitHub Actions / Run tests on pre-built kernel (6.7)
Check failure on line 12 in internal/auxv_pre_go121.go GitHub Actions / Run tests on pre-built kernel (6.7)
Check failure on line 12 in internal/auxv_pre_go121.go GitHub Actions / Run tests on pre-built kernel (6.7)
Check failure on line 12 in internal/auxv_pre_go121.go GitHub Actions / Run tests on pre-built kernel (6.7)
Check failure on line 12 in internal/auxv_pre_go121.go GitHub Actions / Run tests on pre-built kernel (5.10)
Check failure on line 12 in internal/auxv_pre_go121.go GitHub Actions / Run tests on pre-built kernel (5.10)
Check failure on line 12 in internal/auxv_pre_go121.go GitHub Actions / Run tests on pre-built kernel (5.10)
Check failure on line 12 in internal/auxv_pre_go121.go GitHub Actions / Run tests on pre-built kernel (5.10)
Check failure on line 12 in internal/auxv_pre_go121.go GitHub Actions / Run tests on pre-built kernel (4.14)
Check failure on line 12 in internal/auxv_pre_go121.go GitHub Actions / Run tests on pre-built kernel (4.14)
Check failure on line 12 in internal/auxv_pre_go121.go GitHub Actions / Run tests on pre-built kernel (4.14)
|
||
} |