diff --git a/lib/std/os/linux/bpf.zig b/lib/std/os/linux/bpf.zig index 928c157c42..870e405f18 100644 --- a/lib/std/os/linux/bpf.zig +++ b/lib/std/os/linux/bpf.zig @@ -7,6 +7,8 @@ usingnamespace std.os; const std = @import("../../std.zig"); const expectEqual = std.testing.expectEqual; +pub const btf = @import("bpf/btf.zig"); + // instruction classes pub const LD = 0x00; pub const LDX = 0x01; diff --git a/lib/std/os/linux/bpf/btf.zig b/lib/std/os/linux/bpf/btf.zig new file mode 100644 index 0000000000..36560416fb --- /dev/null +++ b/lib/std/os/linux/bpf/btf.zig @@ -0,0 +1,151 @@ +const magic = 0xeb9f; +const version = 1; + +pub const ext = @import("ext.zig"); + +/// All offsets are in bytes relative to the end of this header +pub const Header = packed struct { + magic: u16, + version: u8, + flags: u8, + hdr_len: u32, + + /// offset of type section + type_off: u32, + + /// length of type section + type_len: u32, + + /// offset of string section + str_off: u32, + + /// length of string section + str_len: u32, +}; + +/// Max number of type identifiers +pub const max_type = 0xfffff; + +/// Max offset into string section +pub const max_name_offset = 0xffffff; + +/// Max number of struct/union/enum member of func args +pub const max_vlen = 0xffff; + +pub const Type = packed struct { + name_off: u32, + info: struct { + /// number of struct's members + vlen: u16, + + unused_1: u8, + kind: Kind, + unused_2: u3, + + /// used by Struct, Union, and Fwd + kind_flag: bool, + }, + + /// size is used by Int, Enum, Struct, Union, and DataSec, it tells the size + /// of the type it is describing + /// + /// type is used by Ptr, Typedef, Volatile, Const, Restrict, Func, + /// FuncProto, and Var. It is a type_id referring to another type + size_type: union { size: u32, typ: u32 }, +}; + +/// For some kinds, Type is immediately followed by extra data +pub const Kind = enum(u4) { + Unknown, + Int, + Ptr, + Array, + Struct, + Union, + Enum, + Fwd, + Typedef, + Volatile, + Const, + Restrict, + Func, + FuncProto, + Var, + DataSec, +}; + +/// Int kind is followed by this struct +pub const IntInfo = packed struct { + bits: u8, + unused: u8, + offset: u8, + encoding: enum(u4) { + Signed = 1 << 0, + Char = 1 << 1, + Bool = 1 << 2, + }, +}; + +test "IntInfo is 32 bits" { + std.testing.expectEqual(@bitSizeOf(IntInfo), 32); +} + +/// Enum kind is followed by this struct +pub const Enum = packed struct { + name_off: u32, + val: i32, +}; + +/// Array kind is followd by this struct +pub const Array = packed struct { + typ: u32, + index_type: u32, + nelems: u32, +}; + +/// Struct and Union kinds are followed by multiple Member structs. The exact +/// number is stored in vlen +pub const Member = packed struct { + name_off: u32, + typ: u32, + + /// if the kind_flag is set, offset contains both member bitfield size and + /// bit offset, the bitfield size is set for bitfield members. If the type + /// info kind_flag is not set, the offset contains only bit offset + offset: packed struct { + bit: u24, + bitfield_size: u8, + }, +}; + +/// FuncProto is followed by multiple Params, the exact number is stored in vlen +pub const Param = packed struct { + name_off: u32, + typ: u32, +}; + +pub const VarLinkage = enum { + Static, + GlobalAllocated, + GlobalExtern, +}; + +pub const FuncLinkage = enum { + Static, + Global, + Extern, +}; + +/// Var kind is followd by a single Var struct to describe additional +/// information related to the variable such as its linkage +pub const Var = packed struct { + linkage: u32, +}; + +/// Datasec kind is followed by multible VarSecInfo to describe all Var kind +/// types it contains along with it's in-section offset as well as size. +pub const VarSecInfo = packed struct { + typ: u32, + offset: u32, + size: u32, +}; diff --git a/lib/std/os/linux/bpf/btf_ext.zig b/lib/std/os/linux/bpf/btf_ext.zig new file mode 100644 index 0000000000..05d5d57059 --- /dev/null +++ b/lib/std/os/linux/bpf/btf_ext.zig @@ -0,0 +1,19 @@ +pub const Header = packed struct { + magic: u16, + version: u8, + flags: u8, + hdr_len: u32, + + /// All offsets are in bytes relative to the end of this header + func_info_off: u32, + func_info_len: u32, + line_info_off: u32, + line_info_len: u32, +}; + +pub const InfoSec = packed struct { + sec_name_off: u32, + num_info: u32, + // TODO: communicate that there is data here + //data: [0]u8, +};