github.com/kubeshark/ebpf@v0.9.2/btf/btf_types.go (about) 1 package btf 2 3 import ( 4 "encoding/binary" 5 "fmt" 6 "io" 7 ) 8 9 //go:generate stringer -linecomment -output=btf_types_string.go -type=FuncLinkage,VarLinkage 10 11 // btfKind describes a Type. 12 type btfKind uint8 13 14 // Equivalents of the BTF_KIND_* constants. 15 const ( 16 kindUnknown btfKind = iota 17 kindInt 18 kindPointer 19 kindArray 20 kindStruct 21 kindUnion 22 kindEnum 23 kindForward 24 kindTypedef 25 kindVolatile 26 kindConst 27 kindRestrict 28 // Added ~4.20 29 kindFunc 30 kindFuncProto 31 // Added ~5.1 32 kindVar 33 kindDatasec 34 // Added ~5.13 35 kindFloat 36 ) 37 38 // FuncLinkage describes BTF function linkage metadata. 39 type FuncLinkage int 40 41 // Equivalent of enum btf_func_linkage. 42 const ( 43 StaticFunc FuncLinkage = iota // static 44 GlobalFunc // global 45 ExternFunc // extern 46 ) 47 48 // VarLinkage describes BTF variable linkage metadata. 49 type VarLinkage int 50 51 const ( 52 StaticVar VarLinkage = iota // static 53 GlobalVar // global 54 ExternVar // extern 55 ) 56 57 const ( 58 btfTypeKindShift = 24 59 btfTypeKindLen = 5 60 btfTypeVlenShift = 0 61 btfTypeVlenMask = 16 62 btfTypeKindFlagShift = 31 63 btfTypeKindFlagMask = 1 64 ) 65 66 // btfType is equivalent to struct btf_type in Documentation/bpf/btf.rst. 67 type btfType struct { 68 NameOff uint32 69 /* "info" bits arrangement 70 * bits 0-15: vlen (e.g. # of struct's members), linkage 71 * bits 16-23: unused 72 * bits 24-28: kind (e.g. int, ptr, array...etc) 73 * bits 29-30: unused 74 * bit 31: kind_flag, currently used by 75 * struct, union and fwd 76 */ 77 Info uint32 78 /* "size" is used by INT, ENUM, STRUCT and UNION. 79 * "size" tells the size of the type it is describing. 80 * 81 * "type" is used by PTR, TYPEDEF, VOLATILE, CONST, RESTRICT, 82 * FUNC and FUNC_PROTO. 83 * "type" is a type_id referring to another type. 84 */ 85 SizeType uint32 86 } 87 88 func (k btfKind) String() string { 89 switch k { 90 case kindUnknown: 91 return "Unknown" 92 case kindInt: 93 return "Integer" 94 case kindPointer: 95 return "Pointer" 96 case kindArray: 97 return "Array" 98 case kindStruct: 99 return "Struct" 100 case kindUnion: 101 return "Union" 102 case kindEnum: 103 return "Enumeration" 104 case kindForward: 105 return "Forward" 106 case kindTypedef: 107 return "Typedef" 108 case kindVolatile: 109 return "Volatile" 110 case kindConst: 111 return "Const" 112 case kindRestrict: 113 return "Restrict" 114 case kindFunc: 115 return "Function" 116 case kindFuncProto: 117 return "Function Proto" 118 case kindVar: 119 return "Variable" 120 case kindDatasec: 121 return "Section" 122 case kindFloat: 123 return "Float" 124 default: 125 return fmt.Sprintf("Unknown (%d)", k) 126 } 127 } 128 129 func mask(len uint32) uint32 { 130 return (1 << len) - 1 131 } 132 133 func readBits(value, len, shift uint32) uint32 { 134 return (value >> shift) & mask(len) 135 } 136 137 func writeBits(value, len, shift, new uint32) uint32 { 138 value &^= mask(len) << shift 139 value |= (new & mask(len)) << shift 140 return value 141 } 142 143 func (bt *btfType) info(len, shift uint32) uint32 { 144 return readBits(bt.Info, len, shift) 145 } 146 147 func (bt *btfType) setInfo(value, len, shift uint32) { 148 bt.Info = writeBits(bt.Info, len, shift, value) 149 } 150 151 func (bt *btfType) Kind() btfKind { 152 return btfKind(bt.info(btfTypeKindLen, btfTypeKindShift)) 153 } 154 155 func (bt *btfType) SetKind(kind btfKind) { 156 bt.setInfo(uint32(kind), btfTypeKindLen, btfTypeKindShift) 157 } 158 159 func (bt *btfType) Vlen() int { 160 return int(bt.info(btfTypeVlenMask, btfTypeVlenShift)) 161 } 162 163 func (bt *btfType) SetVlen(vlen int) { 164 bt.setInfo(uint32(vlen), btfTypeVlenMask, btfTypeVlenShift) 165 } 166 167 func (bt *btfType) KindFlag() bool { 168 return bt.info(btfTypeKindFlagMask, btfTypeKindFlagShift) == 1 169 } 170 171 func (bt *btfType) Linkage() FuncLinkage { 172 return FuncLinkage(bt.info(btfTypeVlenMask, btfTypeVlenShift)) 173 } 174 175 func (bt *btfType) SetLinkage(linkage FuncLinkage) { 176 bt.setInfo(uint32(linkage), btfTypeVlenMask, btfTypeVlenShift) 177 } 178 179 func (bt *btfType) Type() TypeID { 180 // TODO: Panic here if wrong kind? 181 return TypeID(bt.SizeType) 182 } 183 184 func (bt *btfType) Size() uint32 { 185 // TODO: Panic here if wrong kind? 186 return bt.SizeType 187 } 188 189 func (bt *btfType) SetSize(size uint32) { 190 bt.SizeType = size 191 } 192 193 type rawType struct { 194 btfType 195 data interface{} 196 } 197 198 func (rt *rawType) Marshal(w io.Writer, bo binary.ByteOrder) error { 199 if err := binary.Write(w, bo, &rt.btfType); err != nil { 200 return err 201 } 202 203 if rt.data == nil { 204 return nil 205 } 206 207 return binary.Write(w, bo, rt.data) 208 } 209 210 // btfInt encodes additional data for integers. 211 // 212 // ? ? ? ? e e e e o o o o o o o o ? ? ? ? ? ? ? ? b b b b b b b b 213 // ? = undefined 214 // e = encoding 215 // o = offset (bitfields?) 216 // b = bits (bitfields) 217 type btfInt struct { 218 Raw uint32 219 } 220 221 const ( 222 btfIntEncodingLen = 4 223 btfIntEncodingShift = 24 224 btfIntOffsetLen = 8 225 btfIntOffsetShift = 16 226 btfIntBitsLen = 8 227 btfIntBitsShift = 0 228 ) 229 230 func (bi btfInt) Encoding() IntEncoding { 231 return IntEncoding(readBits(bi.Raw, btfIntEncodingLen, btfIntEncodingShift)) 232 } 233 234 func (bi *btfInt) SetEncoding(e IntEncoding) { 235 bi.Raw = writeBits(uint32(bi.Raw), btfIntEncodingLen, btfIntEncodingShift, uint32(e)) 236 } 237 238 func (bi btfInt) Offset() Bits { 239 return Bits(readBits(bi.Raw, btfIntOffsetLen, btfIntOffsetShift)) 240 } 241 242 func (bi *btfInt) SetOffset(offset uint32) { 243 bi.Raw = writeBits(bi.Raw, btfIntOffsetLen, btfIntOffsetShift, offset) 244 } 245 246 func (bi btfInt) Bits() Bits { 247 return Bits(readBits(bi.Raw, btfIntBitsLen, btfIntBitsShift)) 248 } 249 250 func (bi *btfInt) SetBits(bits byte) { 251 bi.Raw = writeBits(bi.Raw, btfIntBitsLen, btfIntBitsShift, uint32(bits)) 252 } 253 254 type btfArray struct { 255 Type TypeID 256 IndexType TypeID 257 Nelems uint32 258 } 259 260 type btfMember struct { 261 NameOff uint32 262 Type TypeID 263 Offset uint32 264 } 265 266 type btfVarSecinfo struct { 267 Type TypeID 268 Offset uint32 269 Size uint32 270 } 271 272 type btfVariable struct { 273 Linkage uint32 274 } 275 276 type btfEnum struct { 277 NameOff uint32 278 Val int32 279 } 280 281 type btfParam struct { 282 NameOff uint32 283 Type TypeID 284 } 285 286 func readTypes(r io.Reader, bo binary.ByteOrder, typeLen uint32) ([]rawType, error) { 287 var header btfType 288 // because of the interleaving between types and struct members it is difficult to 289 // precompute the numbers of raw types this will parse 290 // this "guess" is a good first estimation 291 sizeOfbtfType := uintptr(binary.Size(btfType{})) 292 tyMaxCount := uintptr(typeLen) / sizeOfbtfType / 2 293 types := make([]rawType, 0, tyMaxCount) 294 295 for id := TypeID(1); ; id++ { 296 if err := binary.Read(r, bo, &header); err == io.EOF { 297 return types, nil 298 } else if err != nil { 299 return nil, fmt.Errorf("can't read type info for id %v: %v", id, err) 300 } 301 302 var data interface{} 303 switch header.Kind() { 304 case kindInt: 305 data = new(btfInt) 306 case kindPointer: 307 case kindArray: 308 data = new(btfArray) 309 case kindStruct: 310 fallthrough 311 case kindUnion: 312 data = make([]btfMember, header.Vlen()) 313 case kindEnum: 314 data = make([]btfEnum, header.Vlen()) 315 case kindForward: 316 case kindTypedef: 317 case kindVolatile: 318 case kindConst: 319 case kindRestrict: 320 case kindFunc: 321 case kindFuncProto: 322 data = make([]btfParam, header.Vlen()) 323 case kindVar: 324 data = new(btfVariable) 325 case kindDatasec: 326 data = make([]btfVarSecinfo, header.Vlen()) 327 case kindFloat: 328 default: 329 return nil, fmt.Errorf("type id %v: unknown kind: %v", id, header.Kind()) 330 } 331 332 if data == nil { 333 types = append(types, rawType{header, nil}) 334 continue 335 } 336 337 if err := binary.Read(r, bo, data); err != nil { 338 return nil, fmt.Errorf("type id %d: kind %v: can't read %T: %v", id, header.Kind(), data, err) 339 } 340 341 types = append(types, rawType{header, data}) 342 } 343 }