mirror of
https://github.com/opencontainers/runc.git
synced 2026-07-11 06:03:57 +08:00
bump github.com/cilium/ebpf from 0.12.2 to 0.12.3
Signed-off-by: lfbzhm <lifubang@acmcoder.com>
This commit is contained in:
@@ -4,7 +4,7 @@ go 1.20
|
||||
|
||||
require (
|
||||
github.com/checkpoint-restore/go-criu/v6 v6.3.0
|
||||
github.com/cilium/ebpf v0.12.2
|
||||
github.com/cilium/ebpf v0.12.3
|
||||
github.com/containerd/console v1.0.3
|
||||
github.com/coreos/go-systemd/v22 v22.5.0
|
||||
github.com/cyphar/filepath-securejoin v0.2.4
|
||||
@@ -21,7 +21,7 @@ require (
|
||||
github.com/urfave/cli v1.22.12
|
||||
github.com/vishvananda/netlink v1.1.0
|
||||
golang.org/x/net v0.17.0
|
||||
golang.org/x/sys v0.13.0
|
||||
golang.org/x/sys v0.14.1-0.20231108175955-e4099bfacb8c
|
||||
google.golang.org/protobuf v1.31.0
|
||||
)
|
||||
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
github.com/BurntSushi/toml v1.2.1/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
|
||||
github.com/checkpoint-restore/go-criu/v6 v6.3.0 h1:mIdrSO2cPNWQY1truPg6uHLXyKHk3Z5Odx4wjKOASzA=
|
||||
github.com/checkpoint-restore/go-criu/v6 v6.3.0/go.mod h1:rrRTN/uSwY2X+BPRl/gkulo9gsKOSAeVp9/K2tv7xZI=
|
||||
github.com/cilium/ebpf v0.12.2 h1:cP3qL4kkl19kr/F+hKqUo9F9pPMVz1oms8C7Qj0AwWk=
|
||||
github.com/cilium/ebpf v0.12.2/go.mod h1:u9H29/Iq+8cy70YqI6p5pfADkFl3vdnV2qXDg5JL0Zo=
|
||||
github.com/cilium/ebpf v0.12.3 h1:8ht6F9MquybnY97at+VDZb3eQQr8ev79RueWeVaEcG4=
|
||||
github.com/cilium/ebpf v0.12.3/go.mod h1:TctK1ivibvI3znr66ljgi4hqOT8EYQjz1KWBfb1UVgM=
|
||||
github.com/containerd/console v1.0.3 h1:lIr7SlA5PxZyMV30bDW0MGbiOPXwc63yRuCP0ARubLw=
|
||||
github.com/containerd/console v1.0.3/go.mod h1:7LqA/THxQ86k76b8c/EMSiaJ3h1eZkMkXar0TQ1gf3U=
|
||||
github.com/coreos/go-systemd/v22 v22.5.0 h1:RrqgGjYQKalulkV8NGVIfkXQf6YYmOyiJKk8iXXhfZs=
|
||||
@@ -71,8 +71,8 @@ golang.org/x/sys v0.0.0-20190606203320-7fc4e5ec1444/go.mod h1:h1NjWce9XRLGQEsW7w
|
||||
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE=
|
||||
golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.14.1-0.20231108175955-e4099bfacb8c h1:3kC/TjQ+xzIblQv39bCOyRk8fbEeJcDHwbyxPUU2BpA=
|
||||
golang.org/x/sys v0.14.1-0.20231108175955-e4099bfacb8c/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
|
||||
google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
|
||||
|
||||
+61
-30
@@ -4,23 +4,23 @@ package asm
|
||||
|
||||
// Source of ALU / ALU64 / Branch operations
|
||||
//
|
||||
// msb lsb
|
||||
// +----+-+---+
|
||||
// |op |S|cls|
|
||||
// +----+-+---+
|
||||
type Source uint8
|
||||
// msb lsb
|
||||
// +------------+-+---+
|
||||
// | op |S|cls|
|
||||
// +------------+-+---+
|
||||
type Source uint16
|
||||
|
||||
const sourceMask OpCode = 0x08
|
||||
const sourceMask OpCode = 0x0008
|
||||
|
||||
// Source bitmask
|
||||
const (
|
||||
// InvalidSource is returned by getters when invoked
|
||||
// on non ALU / branch OpCodes.
|
||||
InvalidSource Source = 0xff
|
||||
InvalidSource Source = 0xffff
|
||||
// ImmSource src is from constant
|
||||
ImmSource Source = 0x00
|
||||
ImmSource Source = 0x0000
|
||||
// RegSource src is from register
|
||||
RegSource Source = 0x08
|
||||
RegSource Source = 0x0008
|
||||
)
|
||||
|
||||
// The Endianness of a byte swap instruction.
|
||||
@@ -39,46 +39,56 @@ const (
|
||||
|
||||
// ALUOp are ALU / ALU64 operations
|
||||
//
|
||||
// msb lsb
|
||||
// +----+-+---+
|
||||
// |OP |s|cls|
|
||||
// +----+-+---+
|
||||
type ALUOp uint8
|
||||
// msb lsb
|
||||
// +-------+----+-+---+
|
||||
// | EXT | OP |s|cls|
|
||||
// +-------+----+-+---+
|
||||
type ALUOp uint16
|
||||
|
||||
const aluMask OpCode = 0xf0
|
||||
const aluMask OpCode = 0x3ff0
|
||||
|
||||
const (
|
||||
// InvalidALUOp is returned by getters when invoked
|
||||
// on non ALU OpCodes
|
||||
InvalidALUOp ALUOp = 0xff
|
||||
InvalidALUOp ALUOp = 0xffff
|
||||
// Add - addition
|
||||
Add ALUOp = 0x00
|
||||
Add ALUOp = 0x0000
|
||||
// Sub - subtraction
|
||||
Sub ALUOp = 0x10
|
||||
Sub ALUOp = 0x0010
|
||||
// Mul - multiplication
|
||||
Mul ALUOp = 0x20
|
||||
Mul ALUOp = 0x0020
|
||||
// Div - division
|
||||
Div ALUOp = 0x30
|
||||
Div ALUOp = 0x0030
|
||||
// SDiv - signed division
|
||||
SDiv ALUOp = Div + 0x0100
|
||||
// Or - bitwise or
|
||||
Or ALUOp = 0x40
|
||||
Or ALUOp = 0x0040
|
||||
// And - bitwise and
|
||||
And ALUOp = 0x50
|
||||
And ALUOp = 0x0050
|
||||
// LSh - bitwise shift left
|
||||
LSh ALUOp = 0x60
|
||||
LSh ALUOp = 0x0060
|
||||
// RSh - bitwise shift right
|
||||
RSh ALUOp = 0x70
|
||||
RSh ALUOp = 0x0070
|
||||
// Neg - sign/unsign signing bit
|
||||
Neg ALUOp = 0x80
|
||||
Neg ALUOp = 0x0080
|
||||
// Mod - modulo
|
||||
Mod ALUOp = 0x90
|
||||
Mod ALUOp = 0x0090
|
||||
// SMod - signed modulo
|
||||
SMod ALUOp = Mod + 0x0100
|
||||
// Xor - bitwise xor
|
||||
Xor ALUOp = 0xa0
|
||||
Xor ALUOp = 0x00a0
|
||||
// Mov - move value from one place to another
|
||||
Mov ALUOp = 0xb0
|
||||
Mov ALUOp = 0x00b0
|
||||
// MovSX8 - move lower 8 bits, sign extended upper bits of target
|
||||
MovSX8 ALUOp = Mov + 0x0100
|
||||
// MovSX16 - move lower 16 bits, sign extended upper bits of target
|
||||
MovSX16 ALUOp = Mov + 0x0200
|
||||
// MovSX32 - move lower 32 bits, sign extended upper bits of target
|
||||
MovSX32 ALUOp = Mov + 0x0300
|
||||
// ArSh - arithmetic shift
|
||||
ArSh ALUOp = 0xc0
|
||||
ArSh ALUOp = 0x00c0
|
||||
// Swap - endian conversions
|
||||
Swap ALUOp = 0xd0
|
||||
Swap ALUOp = 0x00d0
|
||||
)
|
||||
|
||||
// HostTo converts from host to another endianness.
|
||||
@@ -102,6 +112,27 @@ func HostTo(endian Endianness, dst Register, size Size) Instruction {
|
||||
}
|
||||
}
|
||||
|
||||
// BSwap unconditionally reverses the order of bytes in a register.
|
||||
func BSwap(dst Register, size Size) Instruction {
|
||||
var imm int64
|
||||
switch size {
|
||||
case Half:
|
||||
imm = 16
|
||||
case Word:
|
||||
imm = 32
|
||||
case DWord:
|
||||
imm = 64
|
||||
default:
|
||||
return Instruction{OpCode: InvalidOpCode}
|
||||
}
|
||||
|
||||
return Instruction{
|
||||
OpCode: OpCode(ALU64Class).SetALUOp(Swap),
|
||||
Dst: dst,
|
||||
Constant: imm,
|
||||
}
|
||||
}
|
||||
|
||||
// Op returns the OpCode for an ALU operation with a given source.
|
||||
func (op ALUOp) Op(source Source) OpCode {
|
||||
return OpCode(ALU64Class).SetALUOp(op).SetSource(source)
|
||||
|
||||
+29
-19
@@ -8,7 +8,7 @@ func _() {
|
||||
// An "invalid array index" compiler error signifies that the constant values have changed.
|
||||
// Re-run the stringer command to generate them again.
|
||||
var x [1]struct{}
|
||||
_ = x[InvalidSource-255]
|
||||
_ = x[InvalidSource-65535]
|
||||
_ = x[ImmSource-0]
|
||||
_ = x[RegSource-8]
|
||||
}
|
||||
@@ -25,7 +25,7 @@ func (i Source) String() string {
|
||||
return _Source_name_0
|
||||
case i == 8:
|
||||
return _Source_name_1
|
||||
case i == 255:
|
||||
case i == 65535:
|
||||
return _Source_name_2
|
||||
default:
|
||||
return "Source(" + strconv.FormatInt(int64(i), 10) + ")"
|
||||
@@ -62,41 +62,51 @@ func _() {
|
||||
// An "invalid array index" compiler error signifies that the constant values have changed.
|
||||
// Re-run the stringer command to generate them again.
|
||||
var x [1]struct{}
|
||||
_ = x[InvalidALUOp-255]
|
||||
_ = x[InvalidALUOp-65535]
|
||||
_ = x[Add-0]
|
||||
_ = x[Sub-16]
|
||||
_ = x[Mul-32]
|
||||
_ = x[Div-48]
|
||||
_ = x[SDiv-304]
|
||||
_ = x[Or-64]
|
||||
_ = x[And-80]
|
||||
_ = x[LSh-96]
|
||||
_ = x[RSh-112]
|
||||
_ = x[Neg-128]
|
||||
_ = x[Mod-144]
|
||||
_ = x[SMod-400]
|
||||
_ = x[Xor-160]
|
||||
_ = x[Mov-176]
|
||||
_ = x[MovSX8-432]
|
||||
_ = x[MovSX16-688]
|
||||
_ = x[MovSX32-944]
|
||||
_ = x[ArSh-192]
|
||||
_ = x[Swap-208]
|
||||
}
|
||||
|
||||
const _ALUOp_name = "AddSubMulDivOrAndLShRShNegModXorMovArShSwapInvalidALUOp"
|
||||
const _ALUOp_name = "AddSubMulDivOrAndLShRShNegModXorMovArShSwapSDivSModMovSX8MovSX16MovSX32InvalidALUOp"
|
||||
|
||||
var _ALUOp_map = map[ALUOp]string{
|
||||
0: _ALUOp_name[0:3],
|
||||
16: _ALUOp_name[3:6],
|
||||
32: _ALUOp_name[6:9],
|
||||
48: _ALUOp_name[9:12],
|
||||
64: _ALUOp_name[12:14],
|
||||
80: _ALUOp_name[14:17],
|
||||
96: _ALUOp_name[17:20],
|
||||
112: _ALUOp_name[20:23],
|
||||
128: _ALUOp_name[23:26],
|
||||
144: _ALUOp_name[26:29],
|
||||
160: _ALUOp_name[29:32],
|
||||
176: _ALUOp_name[32:35],
|
||||
192: _ALUOp_name[35:39],
|
||||
208: _ALUOp_name[39:43],
|
||||
255: _ALUOp_name[43:55],
|
||||
0: _ALUOp_name[0:3],
|
||||
16: _ALUOp_name[3:6],
|
||||
32: _ALUOp_name[6:9],
|
||||
48: _ALUOp_name[9:12],
|
||||
64: _ALUOp_name[12:14],
|
||||
80: _ALUOp_name[14:17],
|
||||
96: _ALUOp_name[17:20],
|
||||
112: _ALUOp_name[20:23],
|
||||
128: _ALUOp_name[23:26],
|
||||
144: _ALUOp_name[26:29],
|
||||
160: _ALUOp_name[29:32],
|
||||
176: _ALUOp_name[32:35],
|
||||
192: _ALUOp_name[35:39],
|
||||
208: _ALUOp_name[39:43],
|
||||
304: _ALUOp_name[43:47],
|
||||
400: _ALUOp_name[47:51],
|
||||
432: _ALUOp_name[51:57],
|
||||
688: _ALUOp_name[57:64],
|
||||
944: _ALUOp_name[64:71],
|
||||
65535: _ALUOp_name[71:83],
|
||||
}
|
||||
|
||||
func (i ALUOp) String() string {
|
||||
|
||||
+84
-7
@@ -60,6 +60,34 @@ func (ins *Instruction) Unmarshal(r io.Reader, bo binary.ByteOrder) (uint64, err
|
||||
}
|
||||
|
||||
ins.Offset = int16(bo.Uint16(data[2:4]))
|
||||
|
||||
if ins.OpCode.Class().IsALU() {
|
||||
switch ins.OpCode.ALUOp() {
|
||||
case Div:
|
||||
if ins.Offset == 1 {
|
||||
ins.OpCode = ins.OpCode.SetALUOp(SDiv)
|
||||
ins.Offset = 0
|
||||
}
|
||||
case Mod:
|
||||
if ins.Offset == 1 {
|
||||
ins.OpCode = ins.OpCode.SetALUOp(SMod)
|
||||
ins.Offset = 0
|
||||
}
|
||||
case Mov:
|
||||
switch ins.Offset {
|
||||
case 8:
|
||||
ins.OpCode = ins.OpCode.SetALUOp(MovSX8)
|
||||
ins.Offset = 0
|
||||
case 16:
|
||||
ins.OpCode = ins.OpCode.SetALUOp(MovSX16)
|
||||
ins.Offset = 0
|
||||
case 32:
|
||||
ins.OpCode = ins.OpCode.SetALUOp(MovSX32)
|
||||
ins.Offset = 0
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Convert to int32 before widening to int64
|
||||
// to ensure the signed bit is carried over.
|
||||
ins.Constant = int64(int32(bo.Uint32(data[4:8])))
|
||||
@@ -106,8 +134,38 @@ func (ins Instruction) Marshal(w io.Writer, bo binary.ByteOrder) (uint64, error)
|
||||
return 0, fmt.Errorf("can't marshal registers: %s", err)
|
||||
}
|
||||
|
||||
if ins.OpCode.Class().IsALU() {
|
||||
newOffset := int16(0)
|
||||
switch ins.OpCode.ALUOp() {
|
||||
case SDiv:
|
||||
ins.OpCode = ins.OpCode.SetALUOp(Div)
|
||||
newOffset = 1
|
||||
case SMod:
|
||||
ins.OpCode = ins.OpCode.SetALUOp(Mod)
|
||||
newOffset = 1
|
||||
case MovSX8:
|
||||
ins.OpCode = ins.OpCode.SetALUOp(Mov)
|
||||
newOffset = 8
|
||||
case MovSX16:
|
||||
ins.OpCode = ins.OpCode.SetALUOp(Mov)
|
||||
newOffset = 16
|
||||
case MovSX32:
|
||||
ins.OpCode = ins.OpCode.SetALUOp(Mov)
|
||||
newOffset = 32
|
||||
}
|
||||
if newOffset != 0 && ins.Offset != 0 {
|
||||
return 0, fmt.Errorf("extended ALU opcodes should have an .Offset of 0: %s", ins)
|
||||
}
|
||||
ins.Offset = newOffset
|
||||
}
|
||||
|
||||
op, err := ins.OpCode.bpfOpCode()
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
data := make([]byte, InstructionSize)
|
||||
data[0] = byte(ins.OpCode)
|
||||
data[0] = op
|
||||
data[1] = byte(regs)
|
||||
bo.PutUint16(data[2:4], uint16(ins.Offset))
|
||||
bo.PutUint32(data[4:8], uint32(cons))
|
||||
@@ -298,9 +356,9 @@ func (ins Instruction) Format(f fmt.State, c rune) {
|
||||
goto ref
|
||||
}
|
||||
|
||||
fmt.Fprintf(f, "%v ", op)
|
||||
switch cls := op.Class(); {
|
||||
case cls.isLoadOrStore():
|
||||
fmt.Fprintf(f, "%v ", op)
|
||||
switch op.Mode() {
|
||||
case ImmMode:
|
||||
fmt.Fprintf(f, "dst: %s imm: %d", ins.Dst, ins.Constant)
|
||||
@@ -308,21 +366,30 @@ func (ins Instruction) Format(f fmt.State, c rune) {
|
||||
fmt.Fprintf(f, "imm: %d", ins.Constant)
|
||||
case IndMode:
|
||||
fmt.Fprintf(f, "dst: %s src: %s imm: %d", ins.Dst, ins.Src, ins.Constant)
|
||||
case MemMode:
|
||||
case MemMode, MemSXMode:
|
||||
fmt.Fprintf(f, "dst: %s src: %s off: %d imm: %d", ins.Dst, ins.Src, ins.Offset, ins.Constant)
|
||||
case XAddMode:
|
||||
fmt.Fprintf(f, "dst: %s src: %s", ins.Dst, ins.Src)
|
||||
}
|
||||
|
||||
case cls.IsALU():
|
||||
fmt.Fprintf(f, "dst: %s ", ins.Dst)
|
||||
if op.ALUOp() == Swap || op.Source() == ImmSource {
|
||||
fmt.Fprintf(f, "%v", op)
|
||||
if op == Swap.Op(ImmSource) {
|
||||
fmt.Fprintf(f, "%d", ins.Constant)
|
||||
}
|
||||
|
||||
fmt.Fprintf(f, " dst: %s ", ins.Dst)
|
||||
switch {
|
||||
case op.ALUOp() == Swap:
|
||||
break
|
||||
case op.Source() == ImmSource:
|
||||
fmt.Fprintf(f, "imm: %d", ins.Constant)
|
||||
} else {
|
||||
default:
|
||||
fmt.Fprintf(f, "src: %s", ins.Src)
|
||||
}
|
||||
|
||||
case cls.IsJump():
|
||||
fmt.Fprintf(f, "%v ", op)
|
||||
switch jop := op.JumpOp(); jop {
|
||||
case Call:
|
||||
switch ins.Src {
|
||||
@@ -336,6 +403,13 @@ func (ins Instruction) Format(f fmt.State, c rune) {
|
||||
fmt.Fprint(f, BuiltinFunc(ins.Constant))
|
||||
}
|
||||
|
||||
case Ja:
|
||||
if ins.OpCode.Class() == Jump32Class {
|
||||
fmt.Fprintf(f, "imm: %d", ins.Constant)
|
||||
} else {
|
||||
fmt.Fprintf(f, "off: %d", ins.Offset)
|
||||
}
|
||||
|
||||
default:
|
||||
fmt.Fprintf(f, "dst: %s off: %d ", ins.Dst, ins.Offset)
|
||||
if op.Source() == ImmSource {
|
||||
@@ -344,6 +418,8 @@ func (ins Instruction) Format(f fmt.State, c rune) {
|
||||
fmt.Fprintf(f, "src: %s", ins.Src)
|
||||
}
|
||||
}
|
||||
default:
|
||||
fmt.Fprintf(f, "%v ", op)
|
||||
}
|
||||
|
||||
ref:
|
||||
@@ -772,7 +848,8 @@ func (insns Instructions) encodeFunctionReferences() error {
|
||||
}
|
||||
|
||||
switch {
|
||||
case ins.IsFunctionReference() && ins.Constant == -1:
|
||||
case ins.IsFunctionReference() && ins.Constant == -1,
|
||||
ins.OpCode == Ja.opCode(Jump32Class, ImmSource) && ins.Constant == -1:
|
||||
symOffset, ok := symbolOffsets[ins.Reference()]
|
||||
if !ok {
|
||||
return fmt.Errorf("%s at insn %d: symbol %q: %w", ins.OpCode, i, ins.Reference(), ErrUnsatisfiedProgramReference)
|
||||
|
||||
+10
-2
@@ -10,7 +10,7 @@ package asm
|
||||
// +----+-+---+
|
||||
type JumpOp uint8
|
||||
|
||||
const jumpMask OpCode = aluMask
|
||||
const jumpMask OpCode = 0xf0
|
||||
|
||||
const (
|
||||
// InvalidJumpOp is returned by getters when invoked
|
||||
@@ -103,13 +103,21 @@ func (op JumpOp) Reg32(dst, src Register, label string) Instruction {
|
||||
}
|
||||
|
||||
func (op JumpOp) opCode(class Class, source Source) OpCode {
|
||||
if op == Exit || op == Call || op == Ja {
|
||||
if op == Exit || op == Call {
|
||||
return InvalidOpCode
|
||||
}
|
||||
|
||||
return OpCode(class).SetJumpOp(op).SetSource(source)
|
||||
}
|
||||
|
||||
// LongJump returns a jump always instruction with a range of [-2^31, 2^31 - 1].
|
||||
func LongJump(label string) Instruction {
|
||||
return Instruction{
|
||||
OpCode: Ja.opCode(Jump32Class, ImmSource),
|
||||
Constant: -1,
|
||||
}.WithReference(label)
|
||||
}
|
||||
|
||||
// Label adjusts PC to the address of the label.
|
||||
func (op JumpOp) Label(label string) Instruction {
|
||||
if op == Call {
|
||||
|
||||
+21
@@ -24,6 +24,8 @@ const (
|
||||
IndMode Mode = 0x40
|
||||
// MemMode - load from memory
|
||||
MemMode Mode = 0x60
|
||||
// MemSXMode - load from memory, sign extension
|
||||
MemSXMode Mode = 0x80
|
||||
// XAddMode - add atomically across processors.
|
||||
XAddMode Mode = 0xc0
|
||||
)
|
||||
@@ -73,6 +75,11 @@ func LoadMemOp(size Size) OpCode {
|
||||
return OpCode(LdXClass).SetMode(MemMode).SetSize(size)
|
||||
}
|
||||
|
||||
// LoadMemSXOp returns the OpCode to load a value of given size from memory sign extended.
|
||||
func LoadMemSXOp(size Size) OpCode {
|
||||
return OpCode(LdXClass).SetMode(MemSXMode).SetSize(size)
|
||||
}
|
||||
|
||||
// LoadMem emits `dst = *(size *)(src + offset)`.
|
||||
func LoadMem(dst, src Register, offset int16, size Size) Instruction {
|
||||
return Instruction{
|
||||
@@ -83,6 +90,20 @@ func LoadMem(dst, src Register, offset int16, size Size) Instruction {
|
||||
}
|
||||
}
|
||||
|
||||
// LoadMemSX emits `dst = *(size *)(src + offset)` but sign extends dst.
|
||||
func LoadMemSX(dst, src Register, offset int16, size Size) Instruction {
|
||||
if size == DWord {
|
||||
return Instruction{OpCode: InvalidOpCode}
|
||||
}
|
||||
|
||||
return Instruction{
|
||||
OpCode: LoadMemSXOp(size),
|
||||
Dst: dst,
|
||||
Src: src,
|
||||
Offset: offset,
|
||||
}
|
||||
}
|
||||
|
||||
// LoadImmOp returns the OpCode to load an immediate of given size.
|
||||
//
|
||||
// As of kernel 4.20, only DWord size is accepted.
|
||||
|
||||
+8
-4
@@ -13,6 +13,7 @@ func _() {
|
||||
_ = x[AbsMode-32]
|
||||
_ = x[IndMode-64]
|
||||
_ = x[MemMode-96]
|
||||
_ = x[MemSXMode-128]
|
||||
_ = x[XAddMode-192]
|
||||
}
|
||||
|
||||
@@ -21,8 +22,9 @@ const (
|
||||
_Mode_name_1 = "AbsMode"
|
||||
_Mode_name_2 = "IndMode"
|
||||
_Mode_name_3 = "MemMode"
|
||||
_Mode_name_4 = "XAddMode"
|
||||
_Mode_name_5 = "InvalidMode"
|
||||
_Mode_name_4 = "MemSXMode"
|
||||
_Mode_name_5 = "XAddMode"
|
||||
_Mode_name_6 = "InvalidMode"
|
||||
)
|
||||
|
||||
func (i Mode) String() string {
|
||||
@@ -35,10 +37,12 @@ func (i Mode) String() string {
|
||||
return _Mode_name_2
|
||||
case i == 96:
|
||||
return _Mode_name_3
|
||||
case i == 192:
|
||||
case i == 128:
|
||||
return _Mode_name_4
|
||||
case i == 255:
|
||||
case i == 192:
|
||||
return _Mode_name_5
|
||||
case i == 255:
|
||||
return _Mode_name_6
|
||||
default:
|
||||
return "Mode(" + strconv.FormatInt(int64(i), 10) + ")"
|
||||
}
|
||||
|
||||
+46
-14
@@ -66,18 +66,43 @@ func (cls Class) isJumpOrALU() bool {
|
||||
return cls.IsJump() || cls.IsALU()
|
||||
}
|
||||
|
||||
// OpCode is a packed eBPF opcode.
|
||||
// OpCode represents a single operation.
|
||||
// It is not a 1:1 mapping to real eBPF opcodes.
|
||||
//
|
||||
// Its encoding is defined by a Class value:
|
||||
// The encoding varies based on a 3-bit Class:
|
||||
//
|
||||
// msb lsb
|
||||
// +----+-+---+
|
||||
// | ???? |CLS|
|
||||
// +----+-+---+
|
||||
type OpCode uint8
|
||||
// 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0
|
||||
// ??? | CLS
|
||||
//
|
||||
// For ALUClass and ALUCLass32:
|
||||
//
|
||||
// 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0
|
||||
// OPC |S| CLS
|
||||
//
|
||||
// For LdClass, LdXclass, StClass and StXClass:
|
||||
//
|
||||
// 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0
|
||||
// 0 | MDE |SIZ| CLS
|
||||
//
|
||||
// For JumpClass, Jump32Class:
|
||||
//
|
||||
// 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0
|
||||
// 0 | OPC |S| CLS
|
||||
type OpCode uint16
|
||||
|
||||
// InvalidOpCode is returned by setters on OpCode
|
||||
const InvalidOpCode OpCode = 0xff
|
||||
const InvalidOpCode OpCode = 0xffff
|
||||
|
||||
// bpfOpCode returns the actual BPF opcode.
|
||||
func (op OpCode) bpfOpCode() (byte, error) {
|
||||
const opCodeMask = 0xff
|
||||
|
||||
if !valid(op, opCodeMask) {
|
||||
return 0, fmt.Errorf("invalid opcode %x", op)
|
||||
}
|
||||
|
||||
return byte(op & opCodeMask), nil
|
||||
}
|
||||
|
||||
// rawInstructions returns the number of BPF instructions required
|
||||
// to encode this opcode.
|
||||
@@ -147,7 +172,7 @@ func (op OpCode) JumpOp() JumpOp {
|
||||
jumpOp := JumpOp(op & jumpMask)
|
||||
|
||||
// Some JumpOps are only supported by JumpClass, not Jump32Class.
|
||||
if op.Class() == Jump32Class && (jumpOp == Exit || jumpOp == Call || jumpOp == Ja) {
|
||||
if op.Class() == Jump32Class && (jumpOp == Exit || jumpOp == Call) {
|
||||
return InvalidJumpOp
|
||||
}
|
||||
|
||||
@@ -234,17 +259,24 @@ func (op OpCode) String() string {
|
||||
}
|
||||
|
||||
case class.IsALU():
|
||||
if op.ALUOp() == Swap && op.Class() == ALU64Class {
|
||||
// B to make BSwap, uncontitional byte swap
|
||||
f.WriteString("B")
|
||||
}
|
||||
|
||||
f.WriteString(op.ALUOp().String())
|
||||
|
||||
if op.ALUOp() == Swap {
|
||||
// Width for Endian is controlled by Constant
|
||||
f.WriteString(op.Endianness().String())
|
||||
if op.Class() == ALUClass {
|
||||
// Width for Endian is controlled by Constant
|
||||
f.WriteString(op.Endianness().String())
|
||||
}
|
||||
} else {
|
||||
f.WriteString(strings.TrimSuffix(op.Source().String(), "Source"))
|
||||
|
||||
if class == ALUClass {
|
||||
f.WriteString("32")
|
||||
}
|
||||
|
||||
f.WriteString(strings.TrimSuffix(op.Source().String(), "Source"))
|
||||
}
|
||||
|
||||
case class.IsJump():
|
||||
@@ -254,7 +286,7 @@ func (op OpCode) String() string {
|
||||
f.WriteString("32")
|
||||
}
|
||||
|
||||
if jop := op.JumpOp(); jop != Exit && jop != Call {
|
||||
if jop := op.JumpOp(); jop != Exit && jop != Call && jop != Ja {
|
||||
f.WriteString(strings.TrimSuffix(op.Source().String(), "Source"))
|
||||
}
|
||||
|
||||
|
||||
+8
-13
@@ -209,12 +209,7 @@ func loadRawSpec(btf io.ReaderAt, bo binary.ByteOrder, base *Spec) (*Spec, error
|
||||
}
|
||||
}
|
||||
|
||||
rawTypes, rawStrings, err := parseBTF(btf, bo, baseStrings)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
types, err := inflateRawTypes(rawTypes, rawStrings, base)
|
||||
types, rawStrings, err := parseBTF(btf, bo, baseStrings, base)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -322,12 +317,12 @@ func loadKernelSpec() (_ *Spec, fallback bool, _ error) {
|
||||
}
|
||||
defer file.Close()
|
||||
|
||||
spec, err := loadSpecFromELF(file)
|
||||
spec, err := LoadSpecFromReader(file)
|
||||
return spec, true, err
|
||||
}
|
||||
|
||||
// findVMLinux scans multiple well-known paths for vmlinux kernel images.
|
||||
func findVMLinux() (*internal.SafeELFFile, error) {
|
||||
func findVMLinux() (*os.File, error) {
|
||||
release, err := internal.KernelRelease()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -346,7 +341,7 @@ func findVMLinux() (*internal.SafeELFFile, error) {
|
||||
}
|
||||
|
||||
for _, loc := range locations {
|
||||
file, err := internal.OpenSafeELFFile(fmt.Sprintf(loc, release))
|
||||
file, err := os.Open(fmt.Sprintf(loc, release))
|
||||
if errors.Is(err, os.ErrNotExist) {
|
||||
continue
|
||||
}
|
||||
@@ -373,7 +368,7 @@ func guessRawBTFByteOrder(r io.ReaderAt) binary.ByteOrder {
|
||||
|
||||
// parseBTF reads a .BTF section into memory and parses it into a list of
|
||||
// raw types and a string table.
|
||||
func parseBTF(btf io.ReaderAt, bo binary.ByteOrder, baseStrings *stringTable) ([]rawType, *stringTable, error) {
|
||||
func parseBTF(btf io.ReaderAt, bo binary.ByteOrder, baseStrings *stringTable, base *Spec) ([]Type, *stringTable, error) {
|
||||
buf := internal.NewBufferedSectionReader(btf, 0, math.MaxInt64)
|
||||
header, err := parseBTFHeader(buf, bo)
|
||||
if err != nil {
|
||||
@@ -387,12 +382,12 @@ func parseBTF(btf io.ReaderAt, bo binary.ByteOrder, baseStrings *stringTable) ([
|
||||
}
|
||||
|
||||
buf.Reset(io.NewSectionReader(btf, header.typeStart(), int64(header.TypeLen)))
|
||||
rawTypes, err := readTypes(buf, bo, header.TypeLen)
|
||||
types, err := readAndInflateTypes(buf, bo, header.TypeLen, rawStrings, base)
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("can't read types: %w", err)
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
return rawTypes, rawStrings, nil
|
||||
return types, rawStrings, nil
|
||||
}
|
||||
|
||||
type symbol struct {
|
||||
|
||||
+148
-60
@@ -153,6 +153,19 @@ type btfType struct {
|
||||
SizeType uint32
|
||||
}
|
||||
|
||||
var btfTypeSize = int(unsafe.Sizeof(btfType{}))
|
||||
|
||||
func unmarshalBtfType(bt *btfType, b []byte, bo binary.ByteOrder) (int, error) {
|
||||
if len(b) < btfTypeSize {
|
||||
return 0, fmt.Errorf("not enough bytes to unmarshal btfType")
|
||||
}
|
||||
|
||||
bt.NameOff = bo.Uint32(b[0:])
|
||||
bt.Info = bo.Uint32(b[4:])
|
||||
bt.SizeType = bo.Uint32(b[8:])
|
||||
return btfTypeSize, nil
|
||||
}
|
||||
|
||||
func mask(len uint32) uint32 {
|
||||
return (1 << len) - 1
|
||||
}
|
||||
@@ -300,6 +313,17 @@ const (
|
||||
btfIntBitsShift = 0
|
||||
)
|
||||
|
||||
var btfIntLen = int(unsafe.Sizeof(btfInt{}))
|
||||
|
||||
func unmarshalBtfInt(bi *btfInt, b []byte, bo binary.ByteOrder) (int, error) {
|
||||
if len(b) < btfIntLen {
|
||||
return 0, fmt.Errorf("not enough bytes to unmarshal btfInt")
|
||||
}
|
||||
|
||||
bi.Raw = bo.Uint32(b[0:])
|
||||
return btfIntLen, nil
|
||||
}
|
||||
|
||||
func (bi btfInt) Encoding() IntEncoding {
|
||||
return IntEncoding(readBits(bi.Raw, btfIntEncodingLen, btfIntEncodingShift))
|
||||
}
|
||||
@@ -330,102 +354,166 @@ type btfArray struct {
|
||||
Nelems uint32
|
||||
}
|
||||
|
||||
var btfArrayLen = int(unsafe.Sizeof(btfArray{}))
|
||||
|
||||
func unmarshalBtfArray(ba *btfArray, b []byte, bo binary.ByteOrder) (int, error) {
|
||||
if len(b) < btfArrayLen {
|
||||
return 0, fmt.Errorf("not enough bytes to unmarshal btfArray")
|
||||
}
|
||||
|
||||
ba.Type = TypeID(bo.Uint32(b[0:]))
|
||||
ba.IndexType = TypeID(bo.Uint32(b[4:]))
|
||||
ba.Nelems = bo.Uint32(b[8:])
|
||||
return btfArrayLen, nil
|
||||
}
|
||||
|
||||
type btfMember struct {
|
||||
NameOff uint32
|
||||
Type TypeID
|
||||
Offset uint32
|
||||
}
|
||||
|
||||
var btfMemberLen = int(unsafe.Sizeof(btfMember{}))
|
||||
|
||||
func unmarshalBtfMembers(members []btfMember, b []byte, bo binary.ByteOrder) (int, error) {
|
||||
off := 0
|
||||
for i := range members {
|
||||
if off+btfMemberLen > len(b) {
|
||||
return 0, fmt.Errorf("not enough bytes to unmarshal btfMember %d", i)
|
||||
}
|
||||
|
||||
members[i].NameOff = bo.Uint32(b[off+0:])
|
||||
members[i].Type = TypeID(bo.Uint32(b[off+4:]))
|
||||
members[i].Offset = bo.Uint32(b[off+8:])
|
||||
|
||||
off += btfMemberLen
|
||||
}
|
||||
|
||||
return off, nil
|
||||
}
|
||||
|
||||
type btfVarSecinfo struct {
|
||||
Type TypeID
|
||||
Offset uint32
|
||||
Size uint32
|
||||
}
|
||||
|
||||
var btfVarSecinfoLen = int(unsafe.Sizeof(btfVarSecinfo{}))
|
||||
|
||||
func unmarshalBtfVarSecInfos(secinfos []btfVarSecinfo, b []byte, bo binary.ByteOrder) (int, error) {
|
||||
off := 0
|
||||
for i := range secinfos {
|
||||
if off+btfVarSecinfoLen > len(b) {
|
||||
return 0, fmt.Errorf("not enough bytes to unmarshal btfVarSecinfo %d", i)
|
||||
}
|
||||
|
||||
secinfos[i].Type = TypeID(bo.Uint32(b[off+0:]))
|
||||
secinfos[i].Offset = bo.Uint32(b[off+4:])
|
||||
secinfos[i].Size = bo.Uint32(b[off+8:])
|
||||
|
||||
off += btfVarSecinfoLen
|
||||
}
|
||||
|
||||
return off, nil
|
||||
}
|
||||
|
||||
type btfVariable struct {
|
||||
Linkage uint32
|
||||
}
|
||||
|
||||
var btfVariableLen = int(unsafe.Sizeof(btfVariable{}))
|
||||
|
||||
func unmarshalBtfVariable(bv *btfVariable, b []byte, bo binary.ByteOrder) (int, error) {
|
||||
if len(b) < btfVariableLen {
|
||||
return 0, fmt.Errorf("not enough bytes to unmarshal btfVariable")
|
||||
}
|
||||
|
||||
bv.Linkage = bo.Uint32(b[0:])
|
||||
return btfVariableLen, nil
|
||||
}
|
||||
|
||||
type btfEnum struct {
|
||||
NameOff uint32
|
||||
Val uint32
|
||||
}
|
||||
|
||||
var btfEnumLen = int(unsafe.Sizeof(btfEnum{}))
|
||||
|
||||
func unmarshalBtfEnums(enums []btfEnum, b []byte, bo binary.ByteOrder) (int, error) {
|
||||
off := 0
|
||||
for i := range enums {
|
||||
if off+btfEnumLen > len(b) {
|
||||
return 0, fmt.Errorf("not enough bytes to unmarshal btfEnum %d", i)
|
||||
}
|
||||
|
||||
enums[i].NameOff = bo.Uint32(b[off+0:])
|
||||
enums[i].Val = bo.Uint32(b[off+4:])
|
||||
|
||||
off += btfEnumLen
|
||||
}
|
||||
|
||||
return off, nil
|
||||
}
|
||||
|
||||
type btfEnum64 struct {
|
||||
NameOff uint32
|
||||
ValLo32 uint32
|
||||
ValHi32 uint32
|
||||
}
|
||||
|
||||
var btfEnum64Len = int(unsafe.Sizeof(btfEnum64{}))
|
||||
|
||||
func unmarshalBtfEnums64(enums []btfEnum64, b []byte, bo binary.ByteOrder) (int, error) {
|
||||
off := 0
|
||||
for i := range enums {
|
||||
if off+btfEnum64Len > len(b) {
|
||||
return 0, fmt.Errorf("not enough bytes to unmarshal btfEnum64 %d", i)
|
||||
}
|
||||
|
||||
enums[i].NameOff = bo.Uint32(b[off+0:])
|
||||
enums[i].ValLo32 = bo.Uint32(b[off+4:])
|
||||
enums[i].ValHi32 = bo.Uint32(b[off+8:])
|
||||
|
||||
off += btfEnum64Len
|
||||
}
|
||||
|
||||
return off, nil
|
||||
}
|
||||
|
||||
type btfParam struct {
|
||||
NameOff uint32
|
||||
Type TypeID
|
||||
}
|
||||
|
||||
var btfParamLen = int(unsafe.Sizeof(btfParam{}))
|
||||
|
||||
func unmarshalBtfParams(params []btfParam, b []byte, bo binary.ByteOrder) (int, error) {
|
||||
off := 0
|
||||
for i := range params {
|
||||
if off+btfParamLen > len(b) {
|
||||
return 0, fmt.Errorf("not enough bytes to unmarshal btfParam %d", i)
|
||||
}
|
||||
|
||||
params[i].NameOff = bo.Uint32(b[off+0:])
|
||||
params[i].Type = TypeID(bo.Uint32(b[off+4:]))
|
||||
|
||||
off += btfParamLen
|
||||
}
|
||||
|
||||
return off, nil
|
||||
}
|
||||
|
||||
type btfDeclTag struct {
|
||||
ComponentIdx uint32
|
||||
}
|
||||
|
||||
func readTypes(r io.Reader, bo binary.ByteOrder, typeLen uint32) ([]rawType, error) {
|
||||
var header btfType
|
||||
// because of the interleaving between types and struct members it is difficult to
|
||||
// precompute the numbers of raw types this will parse
|
||||
// this "guess" is a good first estimation
|
||||
sizeOfbtfType := uintptr(btfTypeLen)
|
||||
tyMaxCount := uintptr(typeLen) / sizeOfbtfType / 2
|
||||
types := make([]rawType, 0, tyMaxCount)
|
||||
var btfDeclTagLen = int(unsafe.Sizeof(btfDeclTag{}))
|
||||
|
||||
for id := TypeID(1); ; id++ {
|
||||
if err := binary.Read(r, bo, &header); err == io.EOF {
|
||||
return types, nil
|
||||
} else if err != nil {
|
||||
return nil, fmt.Errorf("can't read type info for id %v: %v", id, err)
|
||||
}
|
||||
|
||||
var data interface{}
|
||||
switch header.Kind() {
|
||||
case kindInt:
|
||||
data = new(btfInt)
|
||||
case kindPointer:
|
||||
case kindArray:
|
||||
data = new(btfArray)
|
||||
case kindStruct:
|
||||
fallthrough
|
||||
case kindUnion:
|
||||
data = make([]btfMember, header.Vlen())
|
||||
case kindEnum:
|
||||
data = make([]btfEnum, header.Vlen())
|
||||
case kindForward:
|
||||
case kindTypedef:
|
||||
case kindVolatile:
|
||||
case kindConst:
|
||||
case kindRestrict:
|
||||
case kindFunc:
|
||||
case kindFuncProto:
|
||||
data = make([]btfParam, header.Vlen())
|
||||
case kindVar:
|
||||
data = new(btfVariable)
|
||||
case kindDatasec:
|
||||
data = make([]btfVarSecinfo, header.Vlen())
|
||||
case kindFloat:
|
||||
case kindDeclTag:
|
||||
data = new(btfDeclTag)
|
||||
case kindTypeTag:
|
||||
case kindEnum64:
|
||||
data = make([]btfEnum64, header.Vlen())
|
||||
default:
|
||||
return nil, fmt.Errorf("type id %v: unknown kind: %v", id, header.Kind())
|
||||
}
|
||||
|
||||
if data == nil {
|
||||
types = append(types, rawType{header, nil})
|
||||
continue
|
||||
}
|
||||
|
||||
if err := binary.Read(r, bo, data); err != nil {
|
||||
return nil, fmt.Errorf("type id %d: kind %v: can't read %T: %v", id, header.Kind(), data, err)
|
||||
}
|
||||
|
||||
types = append(types, rawType{header, data})
|
||||
func unmarshalBtfDeclTag(bdt *btfDeclTag, b []byte, bo binary.ByteOrder) (int, error) {
|
||||
if len(b) < btfDeclTagLen {
|
||||
return 0, fmt.Errorf("not enough bytes to unmarshal btfDeclTag")
|
||||
}
|
||||
|
||||
bdt.ComponentIdx = bo.Uint32(b[0:])
|
||||
return btfDeclTagLen, nil
|
||||
}
|
||||
|
||||
+19
-19
@@ -18,8 +18,8 @@ import (
|
||||
// COREFixup is the result of computing a CO-RE relocation for a target.
|
||||
type COREFixup struct {
|
||||
kind coreKind
|
||||
local uint32
|
||||
target uint32
|
||||
local uint64
|
||||
target uint64
|
||||
// True if there is no valid fixup. The instruction is replaced with an
|
||||
// invalid dummy.
|
||||
poison bool
|
||||
@@ -196,12 +196,12 @@ func CORERelocate(relos []*CORERelocation, target *Spec, bo binary.ByteOrder) ([
|
||||
|
||||
result[i] = COREFixup{
|
||||
kind: relo.kind,
|
||||
local: uint32(relo.id),
|
||||
local: uint64(relo.id),
|
||||
// NB: Using relo.id as the target here is incorrect, since
|
||||
// it doesn't match the BTF we generate on the fly. This isn't
|
||||
// too bad for now since there are no uses of the local type ID
|
||||
// in the kernel, yet.
|
||||
target: uint32(relo.id),
|
||||
target: uint64(relo.id),
|
||||
}
|
||||
continue
|
||||
}
|
||||
@@ -311,10 +311,10 @@ var errNoSignedness = errors.New("no signedness")
|
||||
// coreCalculateFixup calculates the fixup for a single local type, target type
|
||||
// and relocation.
|
||||
func coreCalculateFixup(relo *CORERelocation, target Type, targetID TypeID, bo binary.ByteOrder) (COREFixup, error) {
|
||||
fixup := func(local, target uint32) (COREFixup, error) {
|
||||
fixup := func(local, target uint64) (COREFixup, error) {
|
||||
return COREFixup{kind: relo.kind, local: local, target: target}, nil
|
||||
}
|
||||
fixupWithoutValidation := func(local, target uint32) (COREFixup, error) {
|
||||
fixupWithoutValidation := func(local, target uint64) (COREFixup, error) {
|
||||
return COREFixup{kind: relo.kind, local: local, target: target, skipLocalValidation: true}, nil
|
||||
}
|
||||
poison := func() (COREFixup, error) {
|
||||
@@ -346,7 +346,7 @@ func coreCalculateFixup(relo *CORERelocation, target Type, targetID TypeID, bo b
|
||||
return fixup(1, 1)
|
||||
|
||||
case reloTypeIDTarget:
|
||||
return fixup(uint32(relo.id), uint32(targetID))
|
||||
return fixup(uint64(relo.id), uint64(targetID))
|
||||
|
||||
case reloTypeSize:
|
||||
localSize, err := Sizeof(local)
|
||||
@@ -359,7 +359,7 @@ func coreCalculateFixup(relo *CORERelocation, target Type, targetID TypeID, bo b
|
||||
return zero, err
|
||||
}
|
||||
|
||||
return fixup(uint32(localSize), uint32(targetSize))
|
||||
return fixup(uint64(localSize), uint64(targetSize))
|
||||
}
|
||||
|
||||
case reloEnumvalValue, reloEnumvalExists:
|
||||
@@ -376,7 +376,7 @@ func coreCalculateFixup(relo *CORERelocation, target Type, targetID TypeID, bo b
|
||||
return fixup(1, 1)
|
||||
|
||||
case reloEnumvalValue:
|
||||
return fixup(uint32(localValue.Value), uint32(targetValue.Value))
|
||||
return fixup(localValue.Value, targetValue.Value)
|
||||
}
|
||||
|
||||
case reloFieldByteOffset, reloFieldByteSize, reloFieldExists, reloFieldLShiftU64, reloFieldRShiftU64, reloFieldSigned:
|
||||
@@ -405,7 +405,7 @@ func coreCalculateFixup(relo *CORERelocation, target Type, targetID TypeID, bo b
|
||||
return fixup(1, 1)
|
||||
|
||||
case reloFieldByteOffset:
|
||||
return maybeSkipValidation(fixup(localField.offset, targetField.offset))
|
||||
return maybeSkipValidation(fixup(uint64(localField.offset), uint64(targetField.offset)))
|
||||
|
||||
case reloFieldByteSize:
|
||||
localSize, err := Sizeof(localField.Type)
|
||||
@@ -417,24 +417,24 @@ func coreCalculateFixup(relo *CORERelocation, target Type, targetID TypeID, bo b
|
||||
if err != nil {
|
||||
return zero, err
|
||||
}
|
||||
return maybeSkipValidation(fixup(uint32(localSize), uint32(targetSize)))
|
||||
return maybeSkipValidation(fixup(uint64(localSize), uint64(targetSize)))
|
||||
|
||||
case reloFieldLShiftU64:
|
||||
var target uint32
|
||||
var target uint64
|
||||
if bo == binary.LittleEndian {
|
||||
targetSize, err := targetField.sizeBits()
|
||||
if err != nil {
|
||||
return zero, err
|
||||
}
|
||||
|
||||
target = uint32(64 - targetField.bitfieldOffset - targetSize)
|
||||
target = uint64(64 - targetField.bitfieldOffset - targetSize)
|
||||
} else {
|
||||
loadWidth, err := Sizeof(targetField.Type)
|
||||
if err != nil {
|
||||
return zero, err
|
||||
}
|
||||
|
||||
target = uint32(64 - Bits(loadWidth*8) + targetField.bitfieldOffset)
|
||||
target = uint64(64 - Bits(loadWidth*8) + targetField.bitfieldOffset)
|
||||
}
|
||||
return fixupWithoutValidation(0, target)
|
||||
|
||||
@@ -444,7 +444,7 @@ func coreCalculateFixup(relo *CORERelocation, target Type, targetID TypeID, bo b
|
||||
return zero, err
|
||||
}
|
||||
|
||||
return fixupWithoutValidation(0, uint32(64-targetSize))
|
||||
return fixupWithoutValidation(0, uint64(64-targetSize))
|
||||
|
||||
case reloFieldSigned:
|
||||
switch local := UnderlyingType(localField.Type).(type) {
|
||||
@@ -454,7 +454,7 @@ func coreCalculateFixup(relo *CORERelocation, target Type, targetID TypeID, bo b
|
||||
return zero, fmt.Errorf("target isn't *Enum but %T", targetField.Type)
|
||||
}
|
||||
|
||||
return fixup(boolToUint32(local.Signed), boolToUint32(target.Signed))
|
||||
return fixup(boolToUint64(local.Signed), boolToUint64(target.Signed))
|
||||
case *Int:
|
||||
target, ok := as[*Int](targetField.Type)
|
||||
if !ok {
|
||||
@@ -462,8 +462,8 @@ func coreCalculateFixup(relo *CORERelocation, target Type, targetID TypeID, bo b
|
||||
}
|
||||
|
||||
return fixup(
|
||||
uint32(local.Encoding&Signed),
|
||||
uint32(target.Encoding&Signed),
|
||||
uint64(local.Encoding&Signed),
|
||||
uint64(target.Encoding&Signed),
|
||||
)
|
||||
default:
|
||||
return zero, fmt.Errorf("type %T: %w", local, errNoSignedness)
|
||||
@@ -474,7 +474,7 @@ func coreCalculateFixup(relo *CORERelocation, target Type, targetID TypeID, bo b
|
||||
return zero, ErrNotSupported
|
||||
}
|
||||
|
||||
func boolToUint32(val bool) uint32 {
|
||||
func boolToUint64(val bool) uint64 {
|
||||
if val {
|
||||
return 1
|
||||
}
|
||||
|
||||
+6
-6
@@ -556,21 +556,21 @@ func LoadLineInfos(reader io.Reader, bo binary.ByteOrder, recordNum uint32, spec
|
||||
return newLineInfos(lis, spec.strings)
|
||||
}
|
||||
|
||||
func newLineInfo(li bpfLineInfo, strings *stringTable) (*lineInfo, error) {
|
||||
func newLineInfo(li bpfLineInfo, strings *stringTable) (lineInfo, error) {
|
||||
line, err := strings.Lookup(li.LineOff)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("lookup of line: %w", err)
|
||||
return lineInfo{}, fmt.Errorf("lookup of line: %w", err)
|
||||
}
|
||||
|
||||
fileName, err := strings.Lookup(li.FileNameOff)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("lookup of filename: %w", err)
|
||||
return lineInfo{}, fmt.Errorf("lookup of filename: %w", err)
|
||||
}
|
||||
|
||||
lineNumber := li.LineCol >> bpfLineShift
|
||||
lineColumn := li.LineCol & bpfColumnMax
|
||||
|
||||
return &lineInfo{
|
||||
return lineInfo{
|
||||
&Line{
|
||||
fileName,
|
||||
line,
|
||||
@@ -590,7 +590,7 @@ func newLineInfos(blis []bpfLineInfo, strings *stringTable) (LineInfos, error) {
|
||||
if err != nil {
|
||||
return LineInfos{}, fmt.Errorf("offset %d: %w", bli.InsnOff, err)
|
||||
}
|
||||
lis.infos = append(lis.infos, *li)
|
||||
lis.infos = append(lis.infos, li)
|
||||
}
|
||||
sort.Slice(lis.infos, func(i, j int) bool {
|
||||
return lis.infos[i].offset <= lis.infos[j].offset
|
||||
@@ -666,7 +666,6 @@ func parseLineInfos(r io.Reader, bo binary.ByteOrder, strings *stringTable) (map
|
||||
// These records appear after a btf_ext_info_sec header in the line_info
|
||||
// sub-section of .BTF.ext.
|
||||
func parseLineInfoRecords(r io.Reader, bo binary.ByteOrder, recordSize uint32, recordNum uint32, offsetInBytes bool) ([]bpfLineInfo, error) {
|
||||
var out []bpfLineInfo
|
||||
var li bpfLineInfo
|
||||
|
||||
if exp, got := uint32(binary.Size(li)), recordSize; exp != got {
|
||||
@@ -674,6 +673,7 @@ func parseLineInfoRecords(r io.Reader, bo binary.ByteOrder, recordSize uint32, r
|
||||
return nil, fmt.Errorf("expected LineInfo record size %d, but BTF blob contains %d", exp, got)
|
||||
}
|
||||
|
||||
out := make([]bpfLineInfo, 0, recordNum)
|
||||
for i := uint32(0); i < recordNum; i++ {
|
||||
if err := binary.Read(r, bo, &li); err != nil {
|
||||
return nil, fmt.Errorf("can't read line info: %v", err)
|
||||
|
||||
+19
-15
@@ -15,6 +15,7 @@ import (
|
||||
type stringTable struct {
|
||||
base *stringTable
|
||||
offsets []uint32
|
||||
prevIdx int
|
||||
strings []string
|
||||
}
|
||||
|
||||
@@ -61,7 +62,7 @@ func readStringTable(r sizedReader, base *stringTable) (*stringTable, error) {
|
||||
return nil, errors.New("first item in string table is non-empty")
|
||||
}
|
||||
|
||||
return &stringTable{base, offsets, strings}, nil
|
||||
return &stringTable{base, offsets, 0, strings}, nil
|
||||
}
|
||||
|
||||
func splitNull(data []byte, atEOF bool) (advance int, token []byte, err error) {
|
||||
@@ -84,26 +85,29 @@ func (st *stringTable) Lookup(offset uint32) (string, error) {
|
||||
}
|
||||
|
||||
func (st *stringTable) lookup(offset uint32) (string, error) {
|
||||
// Fast path: zero offset is the empty string, looked up frequently.
|
||||
if offset == 0 && st.base == nil {
|
||||
return "", nil
|
||||
}
|
||||
|
||||
// Accesses tend to be globally increasing, so check if the next string is
|
||||
// the one we want. This skips the binary search in about 50% of cases.
|
||||
if st.prevIdx+1 < len(st.offsets) && st.offsets[st.prevIdx+1] == offset {
|
||||
st.prevIdx++
|
||||
return st.strings[st.prevIdx], nil
|
||||
}
|
||||
|
||||
i, found := slices.BinarySearch(st.offsets, offset)
|
||||
if !found {
|
||||
return "", fmt.Errorf("offset %d isn't start of a string", offset)
|
||||
}
|
||||
|
||||
return st.strings[i], nil
|
||||
}
|
||||
|
||||
func (st *stringTable) Marshal(w io.Writer) error {
|
||||
for _, str := range st.strings {
|
||||
_, err := io.WriteString(w, str)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, err = w.Write([]byte{0})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// Set the new increment index, but only if its greater than the current.
|
||||
if i > st.prevIdx+1 {
|
||||
st.prevIdx = i
|
||||
}
|
||||
return nil
|
||||
|
||||
return st.strings[i], nil
|
||||
}
|
||||
|
||||
// Num returns the number of strings in the table.
|
||||
|
||||
+172
-57
@@ -1,6 +1,7 @@
|
||||
package btf
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
@@ -10,6 +11,7 @@ import (
|
||||
"github.com/cilium/ebpf/asm"
|
||||
"github.com/cilium/ebpf/internal"
|
||||
"github.com/cilium/ebpf/internal/sys"
|
||||
"golang.org/x/exp/slices"
|
||||
)
|
||||
|
||||
// Mirrors MAX_RESOLVE_DEPTH in libbpf.
|
||||
@@ -117,7 +119,7 @@ type Int struct {
|
||||
}
|
||||
|
||||
func (i *Int) Format(fs fmt.State, verb rune) {
|
||||
formatType(fs, verb, i, i.Encoding, "size=", i.Size*8)
|
||||
formatType(fs, verb, i, i.Encoding, "size=", i.Size)
|
||||
}
|
||||
|
||||
func (i *Int) TypeName() string { return i.Name }
|
||||
@@ -726,17 +728,22 @@ func (c *copier) copy(typ *Type, transform Transformer) {
|
||||
|
||||
type typeDeque = internal.Deque[*Type]
|
||||
|
||||
// inflateRawTypes takes a list of raw btf types linked via type IDs, and turns
|
||||
// it into a graph of Types connected via pointers.
|
||||
// readAndInflateTypes reads the raw btf type info and turns it into a graph
|
||||
// of Types connected via pointers.
|
||||
//
|
||||
// If base is provided, then the raw types are considered to be of a split BTF
|
||||
// If base is provided, then the types are considered to be of a split BTF
|
||||
// (e.g., a kernel module).
|
||||
//
|
||||
// Returns a slice of types indexed by TypeID. Since BTF ignores compilation
|
||||
// units, multiple types may share the same name. A Type may form a cyclic graph
|
||||
// by pointing at itself.
|
||||
func inflateRawTypes(rawTypes []rawType, rawStrings *stringTable, base *Spec) ([]Type, error) {
|
||||
types := make([]Type, 0, len(rawTypes)+1) // +1 for Void added to base types
|
||||
func readAndInflateTypes(r io.Reader, bo binary.ByteOrder, typeLen uint32, rawStrings *stringTable, base *Spec) ([]Type, error) {
|
||||
// because of the interleaving between types and struct members it is difficult to
|
||||
// precompute the numbers of raw types this will parse
|
||||
// this "guess" is a good first estimation
|
||||
sizeOfbtfType := uintptr(btfTypeLen)
|
||||
tyMaxCount := uintptr(typeLen) / sizeOfbtfType / 2
|
||||
types := make([]Type, 0, tyMaxCount)
|
||||
|
||||
// Void is defined to always be type ID 0, and is thus omitted from BTF.
|
||||
types = append(types, (*Void)(nil))
|
||||
@@ -841,62 +848,128 @@ func inflateRawTypes(rawTypes []rawType, rawStrings *stringTable, base *Spec) ([
|
||||
return members, nil
|
||||
}
|
||||
|
||||
var (
|
||||
buf = make([]byte, 1024)
|
||||
header btfType
|
||||
bInt btfInt
|
||||
bArr btfArray
|
||||
bMembers []btfMember
|
||||
bEnums []btfEnum
|
||||
bParams []btfParam
|
||||
bVariable btfVariable
|
||||
bSecInfos []btfVarSecinfo
|
||||
bDeclTag btfDeclTag
|
||||
bEnums64 []btfEnum64
|
||||
)
|
||||
|
||||
var declTags []*declTag
|
||||
for _, raw := range rawTypes {
|
||||
for {
|
||||
var (
|
||||
id = firstTypeID + TypeID(len(types))
|
||||
typ Type
|
||||
)
|
||||
|
||||
if _, err := io.ReadFull(r, buf[:btfTypeLen]); err == io.EOF {
|
||||
break
|
||||
} else if err != nil {
|
||||
return nil, fmt.Errorf("can't read type info for id %v: %v", id, err)
|
||||
}
|
||||
|
||||
if _, err := unmarshalBtfType(&header, buf[:btfTypeLen], bo); err != nil {
|
||||
return nil, fmt.Errorf("can't unmarshal type info for id %v: %v", id, err)
|
||||
}
|
||||
|
||||
if id < firstTypeID {
|
||||
return nil, fmt.Errorf("no more type IDs")
|
||||
}
|
||||
|
||||
name, err := rawStrings.Lookup(raw.NameOff)
|
||||
name, err := rawStrings.Lookup(header.NameOff)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("get name for type id %d: %w", id, err)
|
||||
}
|
||||
|
||||
switch raw.Kind() {
|
||||
switch header.Kind() {
|
||||
case kindInt:
|
||||
size := raw.Size()
|
||||
bi := raw.data.(*btfInt)
|
||||
if bi.Offset() > 0 || bi.Bits().Bytes() != size {
|
||||
legacyBitfields[id] = [2]Bits{bi.Offset(), bi.Bits()}
|
||||
size := header.Size()
|
||||
buf = buf[:btfIntLen]
|
||||
if _, err := io.ReadFull(r, buf); err != nil {
|
||||
return nil, fmt.Errorf("can't read btfInt, id: %d: %w", id, err)
|
||||
}
|
||||
typ = &Int{name, raw.Size(), bi.Encoding()}
|
||||
if _, err := unmarshalBtfInt(&bInt, buf, bo); err != nil {
|
||||
return nil, fmt.Errorf("can't unmarshal btfInt, id: %d: %w", id, err)
|
||||
}
|
||||
if bInt.Offset() > 0 || bInt.Bits().Bytes() != size {
|
||||
legacyBitfields[id] = [2]Bits{bInt.Offset(), bInt.Bits()}
|
||||
}
|
||||
typ = &Int{name, header.Size(), bInt.Encoding()}
|
||||
|
||||
case kindPointer:
|
||||
ptr := &Pointer{nil}
|
||||
fixup(raw.Type(), &ptr.Target)
|
||||
fixup(header.Type(), &ptr.Target)
|
||||
typ = ptr
|
||||
|
||||
case kindArray:
|
||||
btfArr := raw.data.(*btfArray)
|
||||
arr := &Array{nil, nil, btfArr.Nelems}
|
||||
fixup(btfArr.IndexType, &arr.Index)
|
||||
fixup(btfArr.Type, &arr.Type)
|
||||
buf = buf[:btfArrayLen]
|
||||
if _, err := io.ReadFull(r, buf); err != nil {
|
||||
return nil, fmt.Errorf("can't read btfArray, id: %d: %w", id, err)
|
||||
}
|
||||
if _, err := unmarshalBtfArray(&bArr, buf, bo); err != nil {
|
||||
return nil, fmt.Errorf("can't unmarshal btfArray, id: %d: %w", id, err)
|
||||
}
|
||||
|
||||
arr := &Array{nil, nil, bArr.Nelems}
|
||||
fixup(bArr.IndexType, &arr.Index)
|
||||
fixup(bArr.Type, &arr.Type)
|
||||
typ = arr
|
||||
|
||||
case kindStruct:
|
||||
members, err := convertMembers(raw.data.([]btfMember), raw.Bitfield())
|
||||
vlen := header.Vlen()
|
||||
bMembers = slices.Grow(bMembers[:0], vlen)[:vlen]
|
||||
buf = slices.Grow(buf[:0], vlen*btfMemberLen)[:vlen*btfMemberLen]
|
||||
if _, err := io.ReadFull(r, buf); err != nil {
|
||||
return nil, fmt.Errorf("can't read btfMembers, id: %d: %w", id, err)
|
||||
}
|
||||
if _, err := unmarshalBtfMembers(bMembers, buf, bo); err != nil {
|
||||
return nil, fmt.Errorf("can't unmarshal btfMembers, id: %d: %w", id, err)
|
||||
}
|
||||
|
||||
members, err := convertMembers(bMembers, header.Bitfield())
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("struct %s (id %d): %w", name, id, err)
|
||||
}
|
||||
typ = &Struct{name, raw.Size(), members}
|
||||
typ = &Struct{name, header.Size(), members}
|
||||
|
||||
case kindUnion:
|
||||
members, err := convertMembers(raw.data.([]btfMember), raw.Bitfield())
|
||||
vlen := header.Vlen()
|
||||
bMembers = slices.Grow(bMembers[:0], vlen)[:vlen]
|
||||
buf = slices.Grow(buf[:0], vlen*btfMemberLen)[:vlen*btfMemberLen]
|
||||
if _, err := io.ReadFull(r, buf); err != nil {
|
||||
return nil, fmt.Errorf("can't read btfMembers, id: %d: %w", id, err)
|
||||
}
|
||||
if _, err := unmarshalBtfMembers(bMembers, buf, bo); err != nil {
|
||||
return nil, fmt.Errorf("can't unmarshal btfMembers, id: %d: %w", id, err)
|
||||
}
|
||||
|
||||
members, err := convertMembers(bMembers, header.Bitfield())
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("union %s (id %d): %w", name, id, err)
|
||||
}
|
||||
typ = &Union{name, raw.Size(), members}
|
||||
typ = &Union{name, header.Size(), members}
|
||||
|
||||
case kindEnum:
|
||||
rawvals := raw.data.([]btfEnum)
|
||||
vals := make([]EnumValue, 0, len(rawvals))
|
||||
signed := raw.Signed()
|
||||
for i, btfVal := range rawvals {
|
||||
vlen := header.Vlen()
|
||||
bEnums = slices.Grow(bEnums[:0], vlen)[:vlen]
|
||||
buf = slices.Grow(buf[:0], vlen*btfEnumLen)[:vlen*btfEnumLen]
|
||||
if _, err := io.ReadFull(r, buf); err != nil {
|
||||
return nil, fmt.Errorf("can't read btfEnums, id: %d: %w", id, err)
|
||||
}
|
||||
if _, err := unmarshalBtfEnums(bEnums, buf, bo); err != nil {
|
||||
return nil, fmt.Errorf("can't unmarshal btfEnums, id: %d: %w", id, err)
|
||||
}
|
||||
|
||||
vals := make([]EnumValue, 0, vlen)
|
||||
signed := header.Signed()
|
||||
for i, btfVal := range bEnums {
|
||||
name, err := rawStrings.Lookup(btfVal.NameOff)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("get name for enum value %d: %s", i, err)
|
||||
@@ -908,40 +981,49 @@ func inflateRawTypes(rawTypes []rawType, rawStrings *stringTable, base *Spec) ([
|
||||
}
|
||||
vals = append(vals, EnumValue{name, value})
|
||||
}
|
||||
typ = &Enum{name, raw.Size(), signed, vals}
|
||||
typ = &Enum{name, header.Size(), signed, vals}
|
||||
|
||||
case kindForward:
|
||||
typ = &Fwd{name, raw.FwdKind()}
|
||||
typ = &Fwd{name, header.FwdKind()}
|
||||
|
||||
case kindTypedef:
|
||||
typedef := &Typedef{name, nil}
|
||||
fixup(raw.Type(), &typedef.Type)
|
||||
fixup(header.Type(), &typedef.Type)
|
||||
typ = typedef
|
||||
|
||||
case kindVolatile:
|
||||
volatile := &Volatile{nil}
|
||||
fixup(raw.Type(), &volatile.Type)
|
||||
fixup(header.Type(), &volatile.Type)
|
||||
typ = volatile
|
||||
|
||||
case kindConst:
|
||||
cnst := &Const{nil}
|
||||
fixup(raw.Type(), &cnst.Type)
|
||||
fixup(header.Type(), &cnst.Type)
|
||||
typ = cnst
|
||||
|
||||
case kindRestrict:
|
||||
restrict := &Restrict{nil}
|
||||
fixup(raw.Type(), &restrict.Type)
|
||||
fixup(header.Type(), &restrict.Type)
|
||||
typ = restrict
|
||||
|
||||
case kindFunc:
|
||||
fn := &Func{name, nil, raw.Linkage()}
|
||||
fixup(raw.Type(), &fn.Type)
|
||||
fn := &Func{name, nil, header.Linkage()}
|
||||
fixup(header.Type(), &fn.Type)
|
||||
typ = fn
|
||||
|
||||
case kindFuncProto:
|
||||
rawparams := raw.data.([]btfParam)
|
||||
params := make([]FuncParam, 0, len(rawparams))
|
||||
for i, param := range rawparams {
|
||||
vlen := header.Vlen()
|
||||
bParams = slices.Grow(bParams[:0], vlen)[:vlen]
|
||||
buf = slices.Grow(buf[:0], vlen*btfParamLen)[:vlen*btfParamLen]
|
||||
if _, err := io.ReadFull(r, buf); err != nil {
|
||||
return nil, fmt.Errorf("can't read btfParams, id: %d: %w", id, err)
|
||||
}
|
||||
if _, err := unmarshalBtfParams(bParams, buf, bo); err != nil {
|
||||
return nil, fmt.Errorf("can't unmarshal btfParams, id: %d: %w", id, err)
|
||||
}
|
||||
|
||||
params := make([]FuncParam, 0, vlen)
|
||||
for i, param := range bParams {
|
||||
name, err := rawStrings.Lookup(param.NameOff)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("get name for func proto parameter %d: %s", i, err)
|
||||
@@ -951,57 +1033,90 @@ func inflateRawTypes(rawTypes []rawType, rawStrings *stringTable, base *Spec) ([
|
||||
})
|
||||
}
|
||||
for i := range params {
|
||||
fixup(rawparams[i].Type, ¶ms[i].Type)
|
||||
fixup(bParams[i].Type, ¶ms[i].Type)
|
||||
}
|
||||
|
||||
fp := &FuncProto{nil, params}
|
||||
fixup(raw.Type(), &fp.Return)
|
||||
fixup(header.Type(), &fp.Return)
|
||||
typ = fp
|
||||
|
||||
case kindVar:
|
||||
variable := raw.data.(*btfVariable)
|
||||
v := &Var{name, nil, VarLinkage(variable.Linkage)}
|
||||
fixup(raw.Type(), &v.Type)
|
||||
buf = buf[:btfVariableLen]
|
||||
if _, err := io.ReadFull(r, buf); err != nil {
|
||||
return nil, fmt.Errorf("can't read btfVariable, id: %d: %w", id, err)
|
||||
}
|
||||
if _, err := unmarshalBtfVariable(&bVariable, buf, bo); err != nil {
|
||||
return nil, fmt.Errorf("can't read btfVariable, id: %d: %w", id, err)
|
||||
}
|
||||
|
||||
v := &Var{name, nil, VarLinkage(bVariable.Linkage)}
|
||||
fixup(header.Type(), &v.Type)
|
||||
typ = v
|
||||
|
||||
case kindDatasec:
|
||||
btfVars := raw.data.([]btfVarSecinfo)
|
||||
vars := make([]VarSecinfo, 0, len(btfVars))
|
||||
for _, btfVar := range btfVars {
|
||||
vlen := header.Vlen()
|
||||
bSecInfos = slices.Grow(bSecInfos[:0], vlen)[:vlen]
|
||||
buf = slices.Grow(buf[:0], vlen*btfVarSecinfoLen)[:vlen*btfVarSecinfoLen]
|
||||
if _, err := io.ReadFull(r, buf); err != nil {
|
||||
return nil, fmt.Errorf("can't read btfVarSecInfos, id: %d: %w", id, err)
|
||||
}
|
||||
if _, err := unmarshalBtfVarSecInfos(bSecInfos, buf, bo); err != nil {
|
||||
return nil, fmt.Errorf("can't unmarshal btfVarSecInfos, id: %d: %w", id, err)
|
||||
}
|
||||
|
||||
vars := make([]VarSecinfo, 0, vlen)
|
||||
for _, btfVar := range bSecInfos {
|
||||
vars = append(vars, VarSecinfo{
|
||||
Offset: btfVar.Offset,
|
||||
Size: btfVar.Size,
|
||||
})
|
||||
}
|
||||
for i := range vars {
|
||||
fixup(btfVars[i].Type, &vars[i].Type)
|
||||
fixup(bSecInfos[i].Type, &vars[i].Type)
|
||||
}
|
||||
typ = &Datasec{name, raw.Size(), vars}
|
||||
typ = &Datasec{name, header.Size(), vars}
|
||||
|
||||
case kindFloat:
|
||||
typ = &Float{name, raw.Size()}
|
||||
typ = &Float{name, header.Size()}
|
||||
|
||||
case kindDeclTag:
|
||||
btfIndex := raw.data.(*btfDeclTag).ComponentIdx
|
||||
buf = buf[:btfDeclTagLen]
|
||||
if _, err := io.ReadFull(r, buf); err != nil {
|
||||
return nil, fmt.Errorf("can't read btfDeclTag, id: %d: %w", id, err)
|
||||
}
|
||||
if _, err := unmarshalBtfDeclTag(&bDeclTag, buf, bo); err != nil {
|
||||
return nil, fmt.Errorf("can't read btfDeclTag, id: %d: %w", id, err)
|
||||
}
|
||||
|
||||
btfIndex := bDeclTag.ComponentIdx
|
||||
if uint64(btfIndex) > math.MaxInt {
|
||||
return nil, fmt.Errorf("type id %d: index exceeds int", id)
|
||||
}
|
||||
|
||||
dt := &declTag{nil, name, int(int32(btfIndex))}
|
||||
fixup(raw.Type(), &dt.Type)
|
||||
fixup(header.Type(), &dt.Type)
|
||||
typ = dt
|
||||
|
||||
declTags = append(declTags, dt)
|
||||
|
||||
case kindTypeTag:
|
||||
tt := &typeTag{nil, name}
|
||||
fixup(raw.Type(), &tt.Type)
|
||||
fixup(header.Type(), &tt.Type)
|
||||
typ = tt
|
||||
|
||||
case kindEnum64:
|
||||
rawvals := raw.data.([]btfEnum64)
|
||||
vals := make([]EnumValue, 0, len(rawvals))
|
||||
for i, btfVal := range rawvals {
|
||||
vlen := header.Vlen()
|
||||
bEnums64 = slices.Grow(bEnums64[:0], vlen)[:vlen]
|
||||
buf = slices.Grow(buf[:0], vlen*btfEnum64Len)[:vlen*btfEnum64Len]
|
||||
if _, err := io.ReadFull(r, buf); err != nil {
|
||||
return nil, fmt.Errorf("can't read btfEnum64s, id: %d: %w", id, err)
|
||||
}
|
||||
if _, err := unmarshalBtfEnums64(bEnums64, buf, bo); err != nil {
|
||||
return nil, fmt.Errorf("can't unmarshal btfEnum64s, id: %d: %w", id, err)
|
||||
}
|
||||
|
||||
vals := make([]EnumValue, 0, vlen)
|
||||
for i, btfVal := range bEnums64 {
|
||||
name, err := rawStrings.Lookup(btfVal.NameOff)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("get name for enum64 value %d: %s", i, err)
|
||||
@@ -1009,10 +1124,10 @@ func inflateRawTypes(rawTypes []rawType, rawStrings *stringTable, base *Spec) ([
|
||||
value := (uint64(btfVal.ValHi32) << 32) | uint64(btfVal.ValLo32)
|
||||
vals = append(vals, EnumValue{name, value})
|
||||
}
|
||||
typ = &Enum{name, raw.Size(), raw.Signed(), vals}
|
||||
typ = &Enum{name, header.Size(), header.Signed(), vals}
|
||||
|
||||
default:
|
||||
return nil, fmt.Errorf("type id %d: unknown kind: %v", id, raw.Kind())
|
||||
return nil, fmt.Errorf("type id %d: unknown kind: %v", id, header.Kind())
|
||||
}
|
||||
|
||||
types = append(types, typ)
|
||||
|
||||
+72
-4
@@ -626,17 +626,20 @@ func resolveKconfig(m *MapSpec) error {
|
||||
internal.NativeEndian.PutUint32(data[vsi.Offset:], kv.Kernel())
|
||||
|
||||
case "LINUX_HAS_SYSCALL_WRAPPER":
|
||||
if integer, ok := v.Type.(*btf.Int); !ok || integer.Size != 4 {
|
||||
return fmt.Errorf("variable %s must be a 32 bits integer, got %s", n, v.Type)
|
||||
integer, ok := v.Type.(*btf.Int)
|
||||
if !ok {
|
||||
return fmt.Errorf("variable %s must be an integer, got %s", n, v.Type)
|
||||
}
|
||||
var value uint32 = 1
|
||||
var value uint64 = 1
|
||||
if err := haveSyscallWrapper(); errors.Is(err, ErrNotSupported) {
|
||||
value = 0
|
||||
} else if err != nil {
|
||||
return fmt.Errorf("unable to derive a value for LINUX_HAS_SYSCALL_WRAPPER: %w", err)
|
||||
}
|
||||
|
||||
internal.NativeEndian.PutUint32(data[vsi.Offset:], value)
|
||||
if err := kconfig.PutInteger(data[vsi.Offset:], integer, value); err != nil {
|
||||
return fmt.Errorf("set LINUX_HAS_SYSCALL_WRAPPER: %w", err)
|
||||
}
|
||||
|
||||
default: // Catch CONFIG_*.
|
||||
configs[n] = configInfo{
|
||||
@@ -695,6 +698,71 @@ func LoadCollection(file string) (*Collection, error) {
|
||||
return NewCollection(spec)
|
||||
}
|
||||
|
||||
// Assign the contents of a Collection to a struct.
|
||||
//
|
||||
// This function bridges functionality between bpf2go generated
|
||||
// code and any functionality better implemented in Collection.
|
||||
//
|
||||
// 'to' must be a pointer to a struct. A field of the
|
||||
// struct is updated with values from Programs or Maps if it
|
||||
// has an `ebpf` tag and its type is *Program or *Map.
|
||||
// The tag's value specifies the name of the program or map as
|
||||
// found in the CollectionSpec.
|
||||
//
|
||||
// struct {
|
||||
// Foo *ebpf.Program `ebpf:"xdp_foo"`
|
||||
// Bar *ebpf.Map `ebpf:"bar_map"`
|
||||
// Ignored int
|
||||
// }
|
||||
//
|
||||
// Returns an error if any of the eBPF objects can't be found, or
|
||||
// if the same Map or Program is assigned multiple times.
|
||||
//
|
||||
// Ownership and Close()ing responsibility is transferred to `to`
|
||||
// for any successful assigns. On error `to` is left in an undefined state.
|
||||
func (coll *Collection) Assign(to interface{}) error {
|
||||
assignedMaps := make(map[string]bool)
|
||||
assignedProgs := make(map[string]bool)
|
||||
|
||||
// Assign() only transfers already-loaded Maps and Programs. No extra
|
||||
// loading is done.
|
||||
getValue := func(typ reflect.Type, name string) (interface{}, error) {
|
||||
switch typ {
|
||||
|
||||
case reflect.TypeOf((*Program)(nil)):
|
||||
if p := coll.Programs[name]; p != nil {
|
||||
assignedProgs[name] = true
|
||||
return p, nil
|
||||
}
|
||||
return nil, fmt.Errorf("missing program %q", name)
|
||||
|
||||
case reflect.TypeOf((*Map)(nil)):
|
||||
if m := coll.Maps[name]; m != nil {
|
||||
assignedMaps[name] = true
|
||||
return m, nil
|
||||
}
|
||||
return nil, fmt.Errorf("missing map %q", name)
|
||||
|
||||
default:
|
||||
return nil, fmt.Errorf("unsupported type %s", typ)
|
||||
}
|
||||
}
|
||||
|
||||
if err := assignValues(to, getValue); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Finalize ownership transfer
|
||||
for p := range assignedProgs {
|
||||
delete(coll.Programs, p)
|
||||
}
|
||||
for m := range assignedMaps {
|
||||
delete(coll.Maps, m)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Close frees all maps and programs associated with the collection.
|
||||
//
|
||||
// The collection mustn't be used afterwards.
|
||||
|
||||
+6
-2
@@ -373,7 +373,7 @@ func (ec *elfCode) loadFunctions(section *elfSection) (map[string]asm.Instructio
|
||||
r := bufio.NewReader(section.Open())
|
||||
|
||||
// Decode the section's instruction stream.
|
||||
var insns asm.Instructions
|
||||
insns := make(asm.Instructions, 0, section.Size/asm.InstructionSize)
|
||||
if err := insns.Unmarshal(r, ec.ByteOrder); err != nil {
|
||||
return nil, fmt.Errorf("decoding instructions for section %s: %w", section.Name, err)
|
||||
}
|
||||
@@ -467,10 +467,14 @@ func (ec *elfCode) relocateInstruction(ins *asm.Instruction, rel elf.Symbol) err
|
||||
|
||||
switch target.kind {
|
||||
case mapSection, btfMapSection:
|
||||
if bind != elf.STB_GLOBAL {
|
||||
if bind == elf.STB_LOCAL {
|
||||
return fmt.Errorf("possible erroneous static qualifier on map definition: found reference to %q", name)
|
||||
}
|
||||
|
||||
if bind != elf.STB_GLOBAL {
|
||||
return fmt.Errorf("map %q: unsupported relocation %s", name, bind)
|
||||
}
|
||||
|
||||
if typ != elf.STT_OBJECT && typ != elf.STT_NOTYPE {
|
||||
// STT_NOTYPE is generated on clang < 8 which doesn't tag
|
||||
// relocations appropriately.
|
||||
|
||||
+15
-2
@@ -250,7 +250,20 @@ func putValueNumber(data []byte, typ btf.Type, value string) error {
|
||||
return fmt.Errorf("cannot parse value: %w", err)
|
||||
}
|
||||
|
||||
switch size {
|
||||
return PutInteger(data, integer, n)
|
||||
}
|
||||
|
||||
// PutInteger writes n into data.
|
||||
//
|
||||
// integer determines how much is written into data and what the valid values
|
||||
// are.
|
||||
func PutInteger(data []byte, integer *btf.Int, n uint64) error {
|
||||
// This function should match set_kcfg_value_num in libbpf.
|
||||
if integer.Encoding == btf.Bool && n > 1 {
|
||||
return fmt.Errorf("invalid boolean value: %d", n)
|
||||
}
|
||||
|
||||
switch integer.Size {
|
||||
case 1:
|
||||
data[0] = byte(n)
|
||||
case 2:
|
||||
@@ -260,7 +273,7 @@ func putValueNumber(data []byte, typ btf.Type, value string) error {
|
||||
case 8:
|
||||
internal.NativeEndian.PutUint64(data, uint64(n))
|
||||
default:
|
||||
return fmt.Errorf("size (%d) is not valid, expected: 1, 2, 4 or 8", size)
|
||||
return fmt.Errorf("size (%d) is not valid, expected: 1, 2, 4 or 8", integer.Size)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
||||
+75
-52
@@ -60,7 +60,12 @@ const (
|
||||
BPF_PERF_EVENT AttachType = 41
|
||||
BPF_TRACE_KPROBE_MULTI AttachType = 42
|
||||
BPF_LSM_CGROUP AttachType = 43
|
||||
__MAX_BPF_ATTACH_TYPE AttachType = 44
|
||||
BPF_STRUCT_OPS AttachType = 44
|
||||
BPF_NETFILTER AttachType = 45
|
||||
BPF_TCX_INGRESS AttachType = 46
|
||||
BPF_TCX_EGRESS AttachType = 47
|
||||
BPF_TRACE_UPROBE_MULTI AttachType = 48
|
||||
__MAX_BPF_ATTACH_TYPE AttachType = 49
|
||||
)
|
||||
|
||||
type Cmd uint32
|
||||
@@ -318,7 +323,9 @@ const (
|
||||
BPF_FUNC_tcp_raw_check_syncookie_ipv6 FunctionId = 207
|
||||
BPF_FUNC_ktime_get_tai_ns FunctionId = 208
|
||||
BPF_FUNC_user_ringbuf_drain FunctionId = 209
|
||||
__BPF_FUNC_MAX_ID FunctionId = 210
|
||||
BPF_FUNC_cgrp_storage_get FunctionId = 210
|
||||
BPF_FUNC_cgrp_storage_delete FunctionId = 211
|
||||
__BPF_FUNC_MAX_ID FunctionId = 212
|
||||
)
|
||||
|
||||
type HdrStartOff uint32
|
||||
@@ -341,44 +348,49 @@ const (
|
||||
BPF_LINK_TYPE_PERF_EVENT LinkType = 7
|
||||
BPF_LINK_TYPE_KPROBE_MULTI LinkType = 8
|
||||
BPF_LINK_TYPE_STRUCT_OPS LinkType = 9
|
||||
MAX_BPF_LINK_TYPE LinkType = 10
|
||||
BPF_LINK_TYPE_NETFILTER LinkType = 10
|
||||
BPF_LINK_TYPE_TCX LinkType = 11
|
||||
BPF_LINK_TYPE_UPROBE_MULTI LinkType = 12
|
||||
MAX_BPF_LINK_TYPE LinkType = 13
|
||||
)
|
||||
|
||||
type MapType uint32
|
||||
|
||||
const (
|
||||
BPF_MAP_TYPE_UNSPEC MapType = 0
|
||||
BPF_MAP_TYPE_HASH MapType = 1
|
||||
BPF_MAP_TYPE_ARRAY MapType = 2
|
||||
BPF_MAP_TYPE_PROG_ARRAY MapType = 3
|
||||
BPF_MAP_TYPE_PERF_EVENT_ARRAY MapType = 4
|
||||
BPF_MAP_TYPE_PERCPU_HASH MapType = 5
|
||||
BPF_MAP_TYPE_PERCPU_ARRAY MapType = 6
|
||||
BPF_MAP_TYPE_STACK_TRACE MapType = 7
|
||||
BPF_MAP_TYPE_CGROUP_ARRAY MapType = 8
|
||||
BPF_MAP_TYPE_LRU_HASH MapType = 9
|
||||
BPF_MAP_TYPE_LRU_PERCPU_HASH MapType = 10
|
||||
BPF_MAP_TYPE_LPM_TRIE MapType = 11
|
||||
BPF_MAP_TYPE_ARRAY_OF_MAPS MapType = 12
|
||||
BPF_MAP_TYPE_HASH_OF_MAPS MapType = 13
|
||||
BPF_MAP_TYPE_DEVMAP MapType = 14
|
||||
BPF_MAP_TYPE_SOCKMAP MapType = 15
|
||||
BPF_MAP_TYPE_CPUMAP MapType = 16
|
||||
BPF_MAP_TYPE_XSKMAP MapType = 17
|
||||
BPF_MAP_TYPE_SOCKHASH MapType = 18
|
||||
BPF_MAP_TYPE_CGROUP_STORAGE MapType = 19
|
||||
BPF_MAP_TYPE_REUSEPORT_SOCKARRAY MapType = 20
|
||||
BPF_MAP_TYPE_PERCPU_CGROUP_STORAGE MapType = 21
|
||||
BPF_MAP_TYPE_QUEUE MapType = 22
|
||||
BPF_MAP_TYPE_STACK MapType = 23
|
||||
BPF_MAP_TYPE_SK_STORAGE MapType = 24
|
||||
BPF_MAP_TYPE_DEVMAP_HASH MapType = 25
|
||||
BPF_MAP_TYPE_STRUCT_OPS MapType = 26
|
||||
BPF_MAP_TYPE_RINGBUF MapType = 27
|
||||
BPF_MAP_TYPE_INODE_STORAGE MapType = 28
|
||||
BPF_MAP_TYPE_TASK_STORAGE MapType = 29
|
||||
BPF_MAP_TYPE_BLOOM_FILTER MapType = 30
|
||||
BPF_MAP_TYPE_USER_RINGBUF MapType = 31
|
||||
BPF_MAP_TYPE_UNSPEC MapType = 0
|
||||
BPF_MAP_TYPE_HASH MapType = 1
|
||||
BPF_MAP_TYPE_ARRAY MapType = 2
|
||||
BPF_MAP_TYPE_PROG_ARRAY MapType = 3
|
||||
BPF_MAP_TYPE_PERF_EVENT_ARRAY MapType = 4
|
||||
BPF_MAP_TYPE_PERCPU_HASH MapType = 5
|
||||
BPF_MAP_TYPE_PERCPU_ARRAY MapType = 6
|
||||
BPF_MAP_TYPE_STACK_TRACE MapType = 7
|
||||
BPF_MAP_TYPE_CGROUP_ARRAY MapType = 8
|
||||
BPF_MAP_TYPE_LRU_HASH MapType = 9
|
||||
BPF_MAP_TYPE_LRU_PERCPU_HASH MapType = 10
|
||||
BPF_MAP_TYPE_LPM_TRIE MapType = 11
|
||||
BPF_MAP_TYPE_ARRAY_OF_MAPS MapType = 12
|
||||
BPF_MAP_TYPE_HASH_OF_MAPS MapType = 13
|
||||
BPF_MAP_TYPE_DEVMAP MapType = 14
|
||||
BPF_MAP_TYPE_SOCKMAP MapType = 15
|
||||
BPF_MAP_TYPE_CPUMAP MapType = 16
|
||||
BPF_MAP_TYPE_XSKMAP MapType = 17
|
||||
BPF_MAP_TYPE_SOCKHASH MapType = 18
|
||||
BPF_MAP_TYPE_CGROUP_STORAGE_DEPRECATED MapType = 19
|
||||
BPF_MAP_TYPE_CGROUP_STORAGE MapType = 19
|
||||
BPF_MAP_TYPE_REUSEPORT_SOCKARRAY MapType = 20
|
||||
BPF_MAP_TYPE_PERCPU_CGROUP_STORAGE MapType = 21
|
||||
BPF_MAP_TYPE_QUEUE MapType = 22
|
||||
BPF_MAP_TYPE_STACK MapType = 23
|
||||
BPF_MAP_TYPE_SK_STORAGE MapType = 24
|
||||
BPF_MAP_TYPE_DEVMAP_HASH MapType = 25
|
||||
BPF_MAP_TYPE_STRUCT_OPS MapType = 26
|
||||
BPF_MAP_TYPE_RINGBUF MapType = 27
|
||||
BPF_MAP_TYPE_INODE_STORAGE MapType = 28
|
||||
BPF_MAP_TYPE_TASK_STORAGE MapType = 29
|
||||
BPF_MAP_TYPE_BLOOM_FILTER MapType = 30
|
||||
BPF_MAP_TYPE_USER_RINGBUF MapType = 31
|
||||
BPF_MAP_TYPE_CGRP_STORAGE MapType = 32
|
||||
)
|
||||
|
||||
type ProgType uint32
|
||||
@@ -416,6 +428,7 @@ const (
|
||||
BPF_PROG_TYPE_LSM ProgType = 29
|
||||
BPF_PROG_TYPE_SK_LOOKUP ProgType = 30
|
||||
BPF_PROG_TYPE_SYSCALL ProgType = 31
|
||||
BPF_PROG_TYPE_NETFILTER ProgType = 32
|
||||
)
|
||||
|
||||
type RetCode uint32
|
||||
@@ -594,12 +607,12 @@ func BtfGetNextId(attr *BtfGetNextIdAttr) error {
|
||||
}
|
||||
|
||||
type BtfLoadAttr struct {
|
||||
Btf Pointer
|
||||
BtfLogBuf Pointer
|
||||
BtfSize uint32
|
||||
BtfLogSize uint32
|
||||
BtfLogLevel uint32
|
||||
_ [4]byte
|
||||
Btf Pointer
|
||||
BtfLogBuf Pointer
|
||||
BtfSize uint32
|
||||
BtfLogSize uint32
|
||||
BtfLogLevel uint32
|
||||
BtfLogTrueSize uint32
|
||||
}
|
||||
|
||||
func BtfLoad(attr *BtfLoadAttr) (*FD, error) {
|
||||
@@ -639,7 +652,7 @@ type LinkCreateAttr struct {
|
||||
AttachType AttachType
|
||||
Flags uint32
|
||||
TargetBtfId TypeID
|
||||
_ [28]byte
|
||||
_ [44]byte
|
||||
}
|
||||
|
||||
func LinkCreate(attr *LinkCreateAttr) (*FD, error) {
|
||||
@@ -657,7 +670,7 @@ type LinkCreateIterAttr struct {
|
||||
Flags uint32
|
||||
IterInfo Pointer
|
||||
IterInfoLen uint32
|
||||
_ [20]byte
|
||||
_ [36]byte
|
||||
}
|
||||
|
||||
func LinkCreateIter(attr *LinkCreateIterAttr) (*FD, error) {
|
||||
@@ -678,6 +691,7 @@ type LinkCreateKprobeMultiAttr struct {
|
||||
Syms Pointer
|
||||
Addrs Pointer
|
||||
Cookies Pointer
|
||||
_ [16]byte
|
||||
}
|
||||
|
||||
func LinkCreateKprobeMulti(attr *LinkCreateKprobeMultiAttr) (*FD, error) {
|
||||
@@ -694,7 +708,7 @@ type LinkCreatePerfEventAttr struct {
|
||||
AttachType AttachType
|
||||
Flags uint32
|
||||
BpfCookie uint64
|
||||
_ [24]byte
|
||||
_ [40]byte
|
||||
}
|
||||
|
||||
func LinkCreatePerfEvent(attr *LinkCreatePerfEventAttr) (*FD, error) {
|
||||
@@ -713,7 +727,7 @@ type LinkCreateTracingAttr struct {
|
||||
TargetBtfId BTFID
|
||||
_ [4]byte
|
||||
Cookie uint64
|
||||
_ [16]byte
|
||||
_ [32]byte
|
||||
}
|
||||
|
||||
func LinkCreateTracing(attr *LinkCreateTracingAttr) (*FD, error) {
|
||||
@@ -920,6 +934,8 @@ type ObjGetAttr struct {
|
||||
Pathname Pointer
|
||||
BpfFd uint32
|
||||
FileFlags uint32
|
||||
PathFd int32
|
||||
_ [4]byte
|
||||
}
|
||||
|
||||
func ObjGet(attr *ObjGetAttr) (*FD, error) {
|
||||
@@ -945,6 +961,8 @@ type ObjPinAttr struct {
|
||||
Pathname Pointer
|
||||
BpfFd uint32
|
||||
FileFlags uint32
|
||||
PathFd int32
|
||||
_ [4]byte
|
||||
}
|
||||
|
||||
func ObjPin(attr *ObjPinAttr) error {
|
||||
@@ -953,11 +971,13 @@ func ObjPin(attr *ObjPinAttr) error {
|
||||
}
|
||||
|
||||
type ProgAttachAttr struct {
|
||||
TargetFd uint32
|
||||
AttachBpfFd uint32
|
||||
AttachType uint32
|
||||
AttachFlags uint32
|
||||
ReplaceBpfFd uint32
|
||||
TargetFd uint32
|
||||
AttachBpfFd uint32
|
||||
AttachType uint32
|
||||
AttachFlags uint32
|
||||
ReplaceBpfFd uint32
|
||||
RelativeFd uint32
|
||||
ExpectedRevision uint64
|
||||
}
|
||||
|
||||
func ProgAttach(attr *ProgAttachAttr) error {
|
||||
@@ -1033,7 +1053,7 @@ type ProgLoadAttr struct {
|
||||
FdArray Pointer
|
||||
CoreRelos Pointer
|
||||
CoreReloRecSize uint32
|
||||
_ [4]byte
|
||||
LogTrueSize uint32
|
||||
}
|
||||
|
||||
func ProgLoad(attr *ProgLoadAttr) (*FD, error) {
|
||||
@@ -1052,7 +1072,10 @@ type ProgQueryAttr struct {
|
||||
ProgIds Pointer
|
||||
ProgCount uint32
|
||||
_ [4]byte
|
||||
ProgAttachFlags uint64
|
||||
ProgAttachFlags Pointer
|
||||
LinkIds Pointer
|
||||
LinkAttachFlags Pointer
|
||||
Revision uint64
|
||||
}
|
||||
|
||||
func ProgQuery(attr *ProgQueryAttr) error {
|
||||
|
||||
+23
-9
@@ -7,6 +7,8 @@ import (
|
||||
"io"
|
||||
"math"
|
||||
|
||||
"golang.org/x/exp/slices"
|
||||
|
||||
"github.com/cilium/ebpf/asm"
|
||||
"github.com/cilium/ebpf/btf"
|
||||
"github.com/cilium/ebpf/internal"
|
||||
@@ -57,21 +59,33 @@ func splitSymbols(insns asm.Instructions) (map[string]asm.Instructions, error) {
|
||||
return nil, errors.New("insns is empty")
|
||||
}
|
||||
|
||||
if insns[0].Symbol() == "" {
|
||||
currentSym := insns[0].Symbol()
|
||||
if currentSym == "" {
|
||||
return nil, errors.New("insns must start with a Symbol")
|
||||
}
|
||||
|
||||
var name string
|
||||
start := 0
|
||||
progs := make(map[string]asm.Instructions)
|
||||
for _, ins := range insns {
|
||||
if sym := ins.Symbol(); sym != "" {
|
||||
if progs[sym] != nil {
|
||||
return nil, fmt.Errorf("insns contains duplicate Symbol %s", sym)
|
||||
}
|
||||
name = sym
|
||||
for i, ins := range insns[1:] {
|
||||
i := i + 1
|
||||
|
||||
sym := ins.Symbol()
|
||||
if sym == "" {
|
||||
continue
|
||||
}
|
||||
|
||||
progs[name] = append(progs[name], ins)
|
||||
// New symbol, flush the old one out.
|
||||
progs[currentSym] = slices.Clone(insns[start:i])
|
||||
|
||||
if progs[sym] != nil {
|
||||
return nil, fmt.Errorf("insns contains duplicate Symbol %s", sym)
|
||||
}
|
||||
currentSym = sym
|
||||
start = i
|
||||
}
|
||||
|
||||
if tail := insns[start:]; len(tail) > 0 {
|
||||
progs[currentSym] = slices.Clone(tail)
|
||||
}
|
||||
|
||||
return progs, nil
|
||||
|
||||
+26
-19
@@ -9,6 +9,7 @@ import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
"reflect"
|
||||
"strings"
|
||||
"time"
|
||||
"unsafe"
|
||||
|
||||
@@ -190,26 +191,32 @@ func (ms *MapSpec) Compatible(m *Map) error {
|
||||
return err
|
||||
}
|
||||
|
||||
switch {
|
||||
case m.typ != ms.Type:
|
||||
return fmt.Errorf("expected type %v, got %v: %w", ms.Type, m.typ, ErrMapIncompatible)
|
||||
|
||||
case m.keySize != ms.KeySize:
|
||||
return fmt.Errorf("expected key size %v, got %v: %w", ms.KeySize, m.keySize, ErrMapIncompatible)
|
||||
|
||||
case m.valueSize != ms.ValueSize:
|
||||
return fmt.Errorf("expected value size %v, got %v: %w", ms.ValueSize, m.valueSize, ErrMapIncompatible)
|
||||
|
||||
case m.maxEntries != ms.MaxEntries:
|
||||
return fmt.Errorf("expected max entries %v, got %v: %w", ms.MaxEntries, m.maxEntries, ErrMapIncompatible)
|
||||
|
||||
// BPF_F_RDONLY_PROG is set unconditionally for devmaps. Explicitly allow
|
||||
// this mismatch.
|
||||
case !((ms.Type == DevMap || ms.Type == DevMapHash) && m.flags^ms.Flags == unix.BPF_F_RDONLY_PROG) &&
|
||||
m.flags != ms.Flags:
|
||||
return fmt.Errorf("expected flags %v, got %v: %w", ms.Flags, m.flags, ErrMapIncompatible)
|
||||
diffs := []string{}
|
||||
if m.typ != ms.Type {
|
||||
diffs = append(diffs, fmt.Sprintf("Type: %s changed to %s", m.typ, ms.Type))
|
||||
}
|
||||
return nil
|
||||
if m.keySize != ms.KeySize {
|
||||
diffs = append(diffs, fmt.Sprintf("KeySize: %d changed to %d", m.keySize, ms.KeySize))
|
||||
}
|
||||
if m.valueSize != ms.ValueSize {
|
||||
diffs = append(diffs, fmt.Sprintf("ValueSize: %d changed to %d", m.valueSize, ms.ValueSize))
|
||||
}
|
||||
if m.maxEntries != ms.MaxEntries {
|
||||
diffs = append(diffs, fmt.Sprintf("MaxEntries: %d changed to %d", m.maxEntries, ms.MaxEntries))
|
||||
}
|
||||
|
||||
// BPF_F_RDONLY_PROG is set unconditionally for devmaps. Explicitly allow this
|
||||
// mismatch.
|
||||
if !((ms.Type == DevMap || ms.Type == DevMapHash) && m.flags^ms.Flags == unix.BPF_F_RDONLY_PROG) &&
|
||||
m.flags != ms.Flags {
|
||||
diffs = append(diffs, fmt.Sprintf("Flags: %d changed to %d", m.flags, ms.Flags))
|
||||
}
|
||||
|
||||
if len(diffs) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
return fmt.Errorf("%s: %w", strings.Join(diffs, ", "), ErrMapIncompatible)
|
||||
}
|
||||
|
||||
// Map represents a Map file descriptor.
|
||||
|
||||
-1
@@ -3,7 +3,6 @@
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build !go1.19
|
||||
// +build !go1.19
|
||||
|
||||
package execabs
|
||||
|
||||
|
||||
-1
@@ -3,7 +3,6 @@
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build go1.19
|
||||
// +build go1.19
|
||||
|
||||
package execabs
|
||||
|
||||
|
||||
-2
@@ -3,8 +3,6 @@
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build (aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris || zos) && go1.9
|
||||
// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris zos
|
||||
// +build go1.9
|
||||
|
||||
package unix
|
||||
|
||||
|
||||
-1
@@ -3,7 +3,6 @@
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build gc
|
||||
// +build gc
|
||||
|
||||
#include "textflag.h"
|
||||
|
||||
|
||||
-2
@@ -3,8 +3,6 @@
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build (freebsd || netbsd || openbsd) && gc
|
||||
// +build freebsd netbsd openbsd
|
||||
// +build gc
|
||||
|
||||
#include "textflag.h"
|
||||
|
||||
|
||||
-2
@@ -3,8 +3,6 @@
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build (darwin || dragonfly || freebsd || netbsd || openbsd) && gc
|
||||
// +build darwin dragonfly freebsd netbsd openbsd
|
||||
// +build gc
|
||||
|
||||
#include "textflag.h"
|
||||
|
||||
|
||||
-2
@@ -3,8 +3,6 @@
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build (freebsd || netbsd || openbsd) && gc
|
||||
// +build freebsd netbsd openbsd
|
||||
// +build gc
|
||||
|
||||
#include "textflag.h"
|
||||
|
||||
|
||||
-2
@@ -3,8 +3,6 @@
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build (darwin || freebsd || netbsd || openbsd) && gc
|
||||
// +build darwin freebsd netbsd openbsd
|
||||
// +build gc
|
||||
|
||||
#include "textflag.h"
|
||||
|
||||
|
||||
-2
@@ -3,8 +3,6 @@
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build (darwin || freebsd || netbsd || openbsd) && gc
|
||||
// +build darwin freebsd netbsd openbsd
|
||||
// +build gc
|
||||
|
||||
#include "textflag.h"
|
||||
|
||||
|
||||
-2
@@ -3,8 +3,6 @@
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build (darwin || freebsd || netbsd || openbsd) && gc
|
||||
// +build darwin freebsd netbsd openbsd
|
||||
// +build gc
|
||||
|
||||
#include "textflag.h"
|
||||
|
||||
|
||||
-1
@@ -3,7 +3,6 @@
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build gc
|
||||
// +build gc
|
||||
|
||||
#include "textflag.h"
|
||||
|
||||
|
||||
-1
@@ -3,7 +3,6 @@
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build gc
|
||||
// +build gc
|
||||
|
||||
#include "textflag.h"
|
||||
|
||||
|
||||
-1
@@ -3,7 +3,6 @@
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build gc
|
||||
// +build gc
|
||||
|
||||
#include "textflag.h"
|
||||
|
||||
|
||||
-3
@@ -3,9 +3,6 @@
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build linux && arm64 && gc
|
||||
// +build linux
|
||||
// +build arm64
|
||||
// +build gc
|
||||
|
||||
#include "textflag.h"
|
||||
|
||||
|
||||
-3
@@ -3,9 +3,6 @@
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build linux && loong64 && gc
|
||||
// +build linux
|
||||
// +build loong64
|
||||
// +build gc
|
||||
|
||||
#include "textflag.h"
|
||||
|
||||
|
||||
-3
@@ -3,9 +3,6 @@
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build linux && (mips64 || mips64le) && gc
|
||||
// +build linux
|
||||
// +build mips64 mips64le
|
||||
// +build gc
|
||||
|
||||
#include "textflag.h"
|
||||
|
||||
|
||||
-3
@@ -3,9 +3,6 @@
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build linux && (mips || mipsle) && gc
|
||||
// +build linux
|
||||
// +build mips mipsle
|
||||
// +build gc
|
||||
|
||||
#include "textflag.h"
|
||||
|
||||
|
||||
-3
@@ -3,9 +3,6 @@
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build linux && (ppc64 || ppc64le) && gc
|
||||
// +build linux
|
||||
// +build ppc64 ppc64le
|
||||
// +build gc
|
||||
|
||||
#include "textflag.h"
|
||||
|
||||
|
||||
-2
@@ -3,8 +3,6 @@
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build riscv64 && gc
|
||||
// +build riscv64
|
||||
// +build gc
|
||||
|
||||
#include "textflag.h"
|
||||
|
||||
|
||||
-3
@@ -3,9 +3,6 @@
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build linux && s390x && gc
|
||||
// +build linux
|
||||
// +build s390x
|
||||
// +build gc
|
||||
|
||||
#include "textflag.h"
|
||||
|
||||
|
||||
-1
@@ -3,7 +3,6 @@
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build gc
|
||||
// +build gc
|
||||
|
||||
#include "textflag.h"
|
||||
|
||||
|
||||
-1
@@ -3,7 +3,6 @@
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build gc
|
||||
// +build gc
|
||||
|
||||
#include "textflag.h"
|
||||
|
||||
|
||||
-3
@@ -3,9 +3,6 @@
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build zos && s390x && gc
|
||||
// +build zos
|
||||
// +build s390x
|
||||
// +build gc
|
||||
|
||||
#include "textflag.h"
|
||||
|
||||
|
||||
-1
@@ -3,7 +3,6 @@
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build freebsd
|
||||
// +build freebsd
|
||||
|
||||
package unix
|
||||
|
||||
|
||||
-1
@@ -3,7 +3,6 @@
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris || zos
|
||||
// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris zos
|
||||
|
||||
package unix
|
||||
|
||||
|
||||
-1
@@ -3,7 +3,6 @@
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build aix && ppc
|
||||
// +build aix,ppc
|
||||
|
||||
// Functions to access/create device major and minor numbers matching the
|
||||
// encoding used by AIX.
|
||||
|
||||
-1
@@ -3,7 +3,6 @@
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build aix && ppc64
|
||||
// +build aix,ppc64
|
||||
|
||||
// Functions to access/create device major and minor numbers matching the
|
||||
// encoding used AIX.
|
||||
|
||||
-1
@@ -3,7 +3,6 @@
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build zos && s390x
|
||||
// +build zos,s390x
|
||||
|
||||
// Functions to access/create device major and minor numbers matching the
|
||||
// encoding used by z/OS.
|
||||
|
||||
-1
@@ -3,7 +3,6 @@
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris || zos
|
||||
// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris zos
|
||||
|
||||
package unix
|
||||
|
||||
|
||||
-1
@@ -3,7 +3,6 @@
|
||||
// license that can be found in the LICENSE file.
|
||||
//
|
||||
//go:build armbe || arm64be || m68k || mips || mips64 || mips64p32 || ppc || ppc64 || s390 || s390x || shbe || sparc || sparc64
|
||||
// +build armbe arm64be m68k mips mips64 mips64p32 ppc ppc64 s390 s390x shbe sparc sparc64
|
||||
|
||||
package unix
|
||||
|
||||
|
||||
-1
@@ -3,7 +3,6 @@
|
||||
// license that can be found in the LICENSE file.
|
||||
//
|
||||
//go:build 386 || amd64 || amd64p32 || alpha || arm || arm64 || loong64 || mipsle || mips64le || mips64p32le || nios2 || ppc64le || riscv || riscv64 || sh
|
||||
// +build 386 amd64 amd64p32 alpha arm arm64 loong64 mipsle mips64le mips64p32le nios2 ppc64le riscv riscv64 sh
|
||||
|
||||
package unix
|
||||
|
||||
|
||||
-1
@@ -3,7 +3,6 @@
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris || zos
|
||||
// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris zos
|
||||
|
||||
// Unix environment variables.
|
||||
|
||||
|
||||
-1
@@ -3,7 +3,6 @@
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build zos && s390x
|
||||
// +build zos,s390x
|
||||
|
||||
package unix
|
||||
|
||||
|
||||
+1
-2
@@ -2,8 +2,7 @@
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build dragonfly || freebsd || linux || netbsd || openbsd
|
||||
// +build dragonfly freebsd linux netbsd openbsd
|
||||
//go:build dragonfly || freebsd || linux || netbsd
|
||||
|
||||
package unix
|
||||
|
||||
|
||||
-1
@@ -3,7 +3,6 @@
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build (linux && 386) || (linux && arm) || (linux && mips) || (linux && mipsle) || (linux && ppc)
|
||||
// +build linux,386 linux,arm linux,mips linux,mipsle linux,ppc
|
||||
|
||||
package unix
|
||||
|
||||
|
||||
-1
@@ -3,7 +3,6 @@
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris || zos
|
||||
// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris zos
|
||||
|
||||
package unix
|
||||
|
||||
|
||||
-1
@@ -3,7 +3,6 @@
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build zos && s390x
|
||||
// +build zos,s390x
|
||||
|
||||
package unix
|
||||
|
||||
|
||||
-1
@@ -3,7 +3,6 @@
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build gccgo && !aix && !hurd
|
||||
// +build gccgo,!aix,!hurd
|
||||
|
||||
package unix
|
||||
|
||||
|
||||
-1
@@ -3,7 +3,6 @@
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build gccgo && !aix && !hurd
|
||||
// +build gccgo,!aix,!hurd
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdint.h>
|
||||
|
||||
-1
@@ -3,7 +3,6 @@
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build gccgo && linux && amd64
|
||||
// +build gccgo,linux,amd64
|
||||
|
||||
package unix
|
||||
|
||||
|
||||
-1
@@ -3,7 +3,6 @@
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build linux
|
||||
// +build linux
|
||||
|
||||
package unix
|
||||
|
||||
|
||||
-1
@@ -3,7 +3,6 @@
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build aix || solaris
|
||||
// +build aix solaris
|
||||
|
||||
package unix
|
||||
|
||||
|
||||
-1
@@ -3,7 +3,6 @@
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build darwin || dragonfly || freebsd || hurd || linux || netbsd || openbsd
|
||||
// +build darwin dragonfly freebsd hurd linux netbsd openbsd
|
||||
|
||||
package unix
|
||||
|
||||
|
||||
-1
@@ -3,7 +3,6 @@
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build zos && s390x
|
||||
// +build zos,s390x
|
||||
|
||||
package unix
|
||||
|
||||
|
||||
+1
-2
@@ -560,7 +560,7 @@ ccflags="$@"
|
||||
$2 ~ /^RLIMIT_(AS|CORE|CPU|DATA|FSIZE|LOCKS|MEMLOCK|MSGQUEUE|NICE|NOFILE|NPROC|RSS|RTPRIO|RTTIME|SIGPENDING|STACK)|RLIM_INFINITY/ ||
|
||||
$2 ~ /^PRIO_(PROCESS|PGRP|USER)/ ||
|
||||
$2 ~ /^CLONE_[A-Z_]+/ ||
|
||||
$2 !~ /^(BPF_TIMEVAL|BPF_FIB_LOOKUP_[A-Z]+)$/ &&
|
||||
$2 !~ /^(BPF_TIMEVAL|BPF_FIB_LOOKUP_[A-Z]+|BPF_F_LINK)$/ &&
|
||||
$2 ~ /^(BPF|DLT)_/ ||
|
||||
$2 ~ /^AUDIT_/ ||
|
||||
$2 ~ /^(CLOCK|TIMER)_/ ||
|
||||
@@ -663,7 +663,6 @@ echo '// mkerrors.sh' "$@"
|
||||
echo '// Code generated by the command above; see README.md. DO NOT EDIT.'
|
||||
echo
|
||||
echo "//go:build ${GOARCH} && ${GOOS}"
|
||||
echo "// +build ${GOARCH},${GOOS}"
|
||||
echo
|
||||
go tool cgo -godefs -- "$@" _const.go >_error.out
|
||||
cat _error.out | grep -vf _error.grep | grep -vf _signal.grep
|
||||
|
||||
-1
@@ -3,7 +3,6 @@
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build aix || darwin || dragonfly || freebsd || openbsd || solaris
|
||||
// +build aix darwin dragonfly freebsd openbsd solaris
|
||||
|
||||
package unix
|
||||
|
||||
|
||||
-1
@@ -3,7 +3,6 @@
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build linux || netbsd
|
||||
// +build linux netbsd
|
||||
|
||||
package unix
|
||||
|
||||
|
||||
-1
@@ -3,7 +3,6 @@
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris
|
||||
// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris
|
||||
|
||||
// For Unix, get the pagesize from the runtime.
|
||||
|
||||
|
||||
+29
-81
@@ -8,54 +8,31 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"strconv"
|
||||
"syscall"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
// Pledge implements the pledge syscall.
|
||||
//
|
||||
// The pledge syscall does not accept execpromises on OpenBSD releases
|
||||
// before 6.3.
|
||||
//
|
||||
// execpromises must be empty when Pledge is called on OpenBSD
|
||||
// releases predating 6.3, otherwise an error will be returned.
|
||||
// This changes both the promises and execpromises; use PledgePromises or
|
||||
// PledgeExecpromises to only change the promises or execpromises
|
||||
// respectively.
|
||||
//
|
||||
// For more information see pledge(2).
|
||||
func Pledge(promises, execpromises string) error {
|
||||
maj, min, err := majmin()
|
||||
if err := pledgeAvailable(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
pptr, err := BytePtrFromString(promises)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = pledgeAvailable(maj, min, execpromises)
|
||||
exptr, err := BytePtrFromString(execpromises)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
pptr, err := syscall.BytePtrFromString(promises)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// This variable will hold either a nil unsafe.Pointer or
|
||||
// an unsafe.Pointer to a string (execpromises).
|
||||
var expr unsafe.Pointer
|
||||
|
||||
// If we're running on OpenBSD > 6.2, pass execpromises to the syscall.
|
||||
if maj > 6 || (maj == 6 && min > 2) {
|
||||
exptr, err := syscall.BytePtrFromString(execpromises)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
expr = unsafe.Pointer(exptr)
|
||||
}
|
||||
|
||||
_, _, e := syscall.Syscall(SYS_PLEDGE, uintptr(unsafe.Pointer(pptr)), uintptr(expr), 0)
|
||||
if e != 0 {
|
||||
return e
|
||||
}
|
||||
|
||||
return nil
|
||||
return pledge(pptr, exptr)
|
||||
}
|
||||
|
||||
// PledgePromises implements the pledge syscall.
|
||||
@@ -64,30 +41,16 @@ func Pledge(promises, execpromises string) error {
|
||||
//
|
||||
// For more information see pledge(2).
|
||||
func PledgePromises(promises string) error {
|
||||
maj, min, err := majmin()
|
||||
if err := pledgeAvailable(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
pptr, err := BytePtrFromString(promises)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = pledgeAvailable(maj, min, "")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// This variable holds the execpromises and is always nil.
|
||||
var expr unsafe.Pointer
|
||||
|
||||
pptr, err := syscall.BytePtrFromString(promises)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, _, e := syscall.Syscall(SYS_PLEDGE, uintptr(unsafe.Pointer(pptr)), uintptr(expr), 0)
|
||||
if e != 0 {
|
||||
return e
|
||||
}
|
||||
|
||||
return nil
|
||||
return pledge(pptr, nil)
|
||||
}
|
||||
|
||||
// PledgeExecpromises implements the pledge syscall.
|
||||
@@ -96,30 +59,16 @@ func PledgePromises(promises string) error {
|
||||
//
|
||||
// For more information see pledge(2).
|
||||
func PledgeExecpromises(execpromises string) error {
|
||||
maj, min, err := majmin()
|
||||
if err := pledgeAvailable(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
exptr, err := BytePtrFromString(execpromises)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = pledgeAvailable(maj, min, execpromises)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// This variable holds the promises and is always nil.
|
||||
var pptr unsafe.Pointer
|
||||
|
||||
exptr, err := syscall.BytePtrFromString(execpromises)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, _, e := syscall.Syscall(SYS_PLEDGE, uintptr(pptr), uintptr(unsafe.Pointer(exptr)), 0)
|
||||
if e != 0 {
|
||||
return e
|
||||
}
|
||||
|
||||
return nil
|
||||
return pledge(nil, exptr)
|
||||
}
|
||||
|
||||
// majmin returns major and minor version number for an OpenBSD system.
|
||||
@@ -147,16 +96,15 @@ func majmin() (major int, minor int, err error) {
|
||||
|
||||
// pledgeAvailable checks for availability of the pledge(2) syscall
|
||||
// based on the running OpenBSD version.
|
||||
func pledgeAvailable(maj, min int, execpromises string) error {
|
||||
// If OpenBSD <= 5.9, pledge is not available.
|
||||
if (maj == 5 && min != 9) || maj < 5 {
|
||||
return fmt.Errorf("pledge syscall is not available on OpenBSD %d.%d", maj, min)
|
||||
func pledgeAvailable() error {
|
||||
maj, min, err := majmin()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// If OpenBSD <= 6.2 and execpromises is not empty,
|
||||
// return an error - execpromises is not available before 6.3
|
||||
if (maj < 6 || (maj == 6 && min <= 2)) && execpromises != "" {
|
||||
return fmt.Errorf("cannot use execpromises on OpenBSD %d.%d", maj, min)
|
||||
// Require OpenBSD 6.4 as a minimum.
|
||||
if maj < 6 || (maj == 6 && min <= 3) {
|
||||
return fmt.Errorf("cannot call Pledge on OpenBSD %d.%d", maj, min)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
||||
-1
@@ -3,7 +3,6 @@
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build darwin && !ios
|
||||
// +build darwin,!ios
|
||||
|
||||
package unix
|
||||
|
||||
|
||||
-1
@@ -3,7 +3,6 @@
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build ios
|
||||
// +build ios
|
||||
|
||||
package unix
|
||||
|
||||
|
||||
-1
@@ -3,7 +3,6 @@
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build (darwin && race) || (linux && race) || (freebsd && race)
|
||||
// +build darwin,race linux,race freebsd,race
|
||||
|
||||
package unix
|
||||
|
||||
|
||||
-1
@@ -3,7 +3,6 @@
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build aix || (darwin && !race) || (linux && !race) || (freebsd && !race) || netbsd || openbsd || solaris || dragonfly || zos
|
||||
// +build aix darwin,!race linux,!race freebsd,!race netbsd openbsd solaris dragonfly zos
|
||||
|
||||
package unix
|
||||
|
||||
|
||||
-1
@@ -3,7 +3,6 @@
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build aix || dragonfly || freebsd || linux || netbsd || openbsd
|
||||
// +build aix dragonfly freebsd linux netbsd openbsd
|
||||
|
||||
package unix
|
||||
|
||||
|
||||
-1
@@ -3,7 +3,6 @@
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build darwin
|
||||
// +build darwin
|
||||
|
||||
package unix
|
||||
|
||||
|
||||
-1
@@ -3,7 +3,6 @@
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris || zos
|
||||
// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris zos
|
||||
|
||||
// Socket control messages
|
||||
|
||||
|
||||
-1
@@ -3,7 +3,6 @@
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build aix || darwin || freebsd || linux || netbsd || openbsd || solaris || zos
|
||||
// +build aix darwin freebsd linux netbsd openbsd solaris zos
|
||||
|
||||
package unix
|
||||
|
||||
|
||||
-1
@@ -3,7 +3,6 @@
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris || zos
|
||||
// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris zos
|
||||
|
||||
// Package unix contains an interface to the low-level operating system
|
||||
// primitives. OS details vary depending on the underlying system, and
|
||||
|
||||
+2
-2
@@ -3,7 +3,6 @@
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build aix
|
||||
// +build aix
|
||||
|
||||
// Aix system calls.
|
||||
// This file is compiled as ordinary Go code,
|
||||
@@ -107,7 +106,8 @@ func (sa *SockaddrUnix) sockaddr() (unsafe.Pointer, _Socklen, error) {
|
||||
if n > 0 {
|
||||
sl += _Socklen(n) + 1
|
||||
}
|
||||
if sa.raw.Path[0] == '@' {
|
||||
if sa.raw.Path[0] == '@' || (sa.raw.Path[0] == 0 && sl > 3) {
|
||||
// Check sl > 3 so we don't change unnamed socket behavior.
|
||||
sa.raw.Path[0] = 0
|
||||
// Don't count trailing NUL for abstract address.
|
||||
sl--
|
||||
|
||||
-1
@@ -3,7 +3,6 @@
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build aix && ppc
|
||||
// +build aix,ppc
|
||||
|
||||
package unix
|
||||
|
||||
|
||||
-1
@@ -3,7 +3,6 @@
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build aix && ppc64
|
||||
// +build aix,ppc64
|
||||
|
||||
package unix
|
||||
|
||||
|
||||
+1
-2
@@ -3,7 +3,6 @@
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build darwin || dragonfly || freebsd || netbsd || openbsd
|
||||
// +build darwin dragonfly freebsd netbsd openbsd
|
||||
|
||||
// BSD system call wrappers shared by *BSD based systems
|
||||
// including OS X (Darwin) and FreeBSD. Like the other
|
||||
@@ -317,7 +316,7 @@ func GetsockoptString(fd, level, opt int) (string, error) {
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return string(buf[:vallen-1]), nil
|
||||
return ByteSliceToString(buf[:vallen]), nil
|
||||
}
|
||||
|
||||
//sys recvfrom(fd int, p []byte, flags int, from *RawSockaddrAny, fromlen *_Socklen) (n int, err error)
|
||||
|
||||
-1
@@ -3,7 +3,6 @@
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build amd64 && darwin
|
||||
// +build amd64,darwin
|
||||
|
||||
package unix
|
||||
|
||||
|
||||
-1
@@ -3,7 +3,6 @@
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build arm64 && darwin
|
||||
// +build arm64,darwin
|
||||
|
||||
package unix
|
||||
|
||||
|
||||
-1
@@ -3,7 +3,6 @@
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build darwin && go1.12
|
||||
// +build darwin,go1.12
|
||||
|
||||
package unix
|
||||
|
||||
|
||||
-1
@@ -3,7 +3,6 @@
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build amd64 && dragonfly
|
||||
// +build amd64,dragonfly
|
||||
|
||||
package unix
|
||||
|
||||
|
||||
-1
@@ -3,7 +3,6 @@
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build 386 && freebsd
|
||||
// +build 386,freebsd
|
||||
|
||||
package unix
|
||||
|
||||
|
||||
-1
@@ -3,7 +3,6 @@
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build amd64 && freebsd
|
||||
// +build amd64,freebsd
|
||||
|
||||
package unix
|
||||
|
||||
|
||||
-1
@@ -3,7 +3,6 @@
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build arm && freebsd
|
||||
// +build arm,freebsd
|
||||
|
||||
package unix
|
||||
|
||||
|
||||
-1
@@ -3,7 +3,6 @@
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build arm64 && freebsd
|
||||
// +build arm64,freebsd
|
||||
|
||||
package unix
|
||||
|
||||
|
||||
-1
@@ -3,7 +3,6 @@
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build riscv64 && freebsd
|
||||
// +build riscv64,freebsd
|
||||
|
||||
package unix
|
||||
|
||||
|
||||
-1
@@ -3,7 +3,6 @@
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build hurd
|
||||
// +build hurd
|
||||
|
||||
package unix
|
||||
|
||||
|
||||
-1
@@ -3,7 +3,6 @@
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build 386 && hurd
|
||||
// +build 386,hurd
|
||||
|
||||
package unix
|
||||
|
||||
|
||||
-1
@@ -5,7 +5,6 @@
|
||||
// illumos system calls not present on Solaris.
|
||||
|
||||
//go:build amd64 && illumos
|
||||
// +build amd64,illumos
|
||||
|
||||
package unix
|
||||
|
||||
|
||||
+21
-10
@@ -61,15 +61,23 @@ func FanotifyMark(fd int, flags uint, mask uint64, dirFd int, pathname string) (
|
||||
}
|
||||
|
||||
//sys fchmodat(dirfd int, path string, mode uint32) (err error)
|
||||
//sys fchmodat2(dirfd int, path string, mode uint32, flags int) (err error)
|
||||
|
||||
func Fchmodat(dirfd int, path string, mode uint32, flags int) (err error) {
|
||||
// Linux fchmodat doesn't support the flags parameter. Mimick glibc's behavior
|
||||
// and check the flags. Otherwise the mode would be applied to the symlink
|
||||
// destination which is not what the user expects.
|
||||
if flags&^AT_SYMLINK_NOFOLLOW != 0 {
|
||||
return EINVAL
|
||||
} else if flags&AT_SYMLINK_NOFOLLOW != 0 {
|
||||
return EOPNOTSUPP
|
||||
func Fchmodat(dirfd int, path string, mode uint32, flags int) error {
|
||||
// Linux fchmodat doesn't support the flags parameter, but fchmodat2 does.
|
||||
// Try fchmodat2 if flags are specified.
|
||||
if flags != 0 {
|
||||
err := fchmodat2(dirfd, path, mode, flags)
|
||||
if err == ENOSYS {
|
||||
// fchmodat2 isn't available. If the flags are known to be valid,
|
||||
// return EOPNOTSUPP to indicate that fchmodat doesn't support them.
|
||||
if flags&^(AT_SYMLINK_NOFOLLOW|AT_EMPTY_PATH) != 0 {
|
||||
return EINVAL
|
||||
} else if flags&(AT_SYMLINK_NOFOLLOW|AT_EMPTY_PATH) != 0 {
|
||||
return EOPNOTSUPP
|
||||
}
|
||||
}
|
||||
return err
|
||||
}
|
||||
return fchmodat(dirfd, path, mode)
|
||||
}
|
||||
@@ -417,7 +425,8 @@ func (sa *SockaddrUnix) sockaddr() (unsafe.Pointer, _Socklen, error) {
|
||||
if n > 0 {
|
||||
sl += _Socklen(n) + 1
|
||||
}
|
||||
if sa.raw.Path[0] == '@' {
|
||||
if sa.raw.Path[0] == '@' || (sa.raw.Path[0] == 0 && sl > 3) {
|
||||
// Check sl > 3 so we don't change unnamed socket behavior.
|
||||
sa.raw.Path[0] = 0
|
||||
// Don't count trailing NUL for abstract address.
|
||||
sl--
|
||||
@@ -1301,7 +1310,7 @@ func GetsockoptString(fd, level, opt int) (string, error) {
|
||||
return "", err
|
||||
}
|
||||
}
|
||||
return string(buf[:vallen-1]), nil
|
||||
return ByteSliceToString(buf[:vallen]), nil
|
||||
}
|
||||
|
||||
func GetsockoptTpacketStats(fd, level, opt int) (*TpacketStats, error) {
|
||||
@@ -2482,3 +2491,5 @@ func SchedGetAttr(pid int, flags uint) (*SchedAttr, error) {
|
||||
}
|
||||
return attr, nil
|
||||
}
|
||||
|
||||
//sys Cachestat(fd uint, crange *CachestatRange, cstat *Cachestat_t, flags uint) (err error)
|
||||
|
||||
-1
@@ -3,7 +3,6 @@
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build 386 && linux
|
||||
// +build 386,linux
|
||||
|
||||
package unix
|
||||
|
||||
|
||||
-2
@@ -3,8 +3,6 @@
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build linux && (386 || amd64 || mips || mipsle || mips64 || mipsle || ppc64 || ppc64le || ppc || s390x || sparc64)
|
||||
// +build linux
|
||||
// +build 386 amd64 mips mipsle mips64 mipsle ppc64 ppc64le ppc s390x sparc64
|
||||
|
||||
package unix
|
||||
|
||||
|
||||
-1
@@ -3,7 +3,6 @@
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build amd64 && linux
|
||||
// +build amd64,linux
|
||||
|
||||
package unix
|
||||
|
||||
|
||||
-1
@@ -3,7 +3,6 @@
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build amd64 && linux && gc
|
||||
// +build amd64,linux,gc
|
||||
|
||||
package unix
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user