github.com/cilium/ebpf@v0.15.1-0.20240517100537-8079b37aa138/btf/btf_types.go (about) 1 package btf 2 3 import ( 4 "encoding/binary" 5 "errors" 6 "fmt" 7 "io" 8 "unsafe" 9 10 "github.com/cilium/ebpf/internal" 11 ) 12 13 //go:generate go run golang.org/x/tools/cmd/stringer@latest -linecomment -output=btf_types_string.go -type=FuncLinkage,VarLinkage,btfKind 14 15 // btfKind describes a Type. 16 type btfKind uint8 17 18 // Equivalents of the BTF_KIND_* constants. 19 const ( 20 kindUnknown btfKind = iota // Unknown 21 kindInt // Int 22 kindPointer // Pointer 23 kindArray // Array 24 kindStruct // Struct 25 kindUnion // Union 26 kindEnum // Enum 27 kindForward // Forward 28 kindTypedef // Typedef 29 kindVolatile // Volatile 30 kindConst // Const 31 kindRestrict // Restrict 32 // Added ~4.20 33 kindFunc // Func 34 kindFuncProto // FuncProto 35 // Added ~5.1 36 kindVar // Var 37 kindDatasec // Datasec 38 // Added ~5.13 39 kindFloat // Float 40 // Added 5.16 41 kindDeclTag // DeclTag 42 kindTypeTag // TypeTag 43 // Added 6.0 44 kindEnum64 // Enum64 45 ) 46 47 // FuncLinkage describes BTF function linkage metadata. 48 type FuncLinkage int 49 50 // Equivalent of enum btf_func_linkage. 51 const ( 52 StaticFunc FuncLinkage = iota // static 53 GlobalFunc // global 54 ExternFunc // extern 55 ) 56 57 // VarLinkage describes BTF variable linkage metadata. 58 type VarLinkage int 59 60 const ( 61 StaticVar VarLinkage = iota // static 62 GlobalVar // global 63 ExternVar // extern 64 ) 65 66 const ( 67 btfTypeKindShift = 24 68 btfTypeKindLen = 5 69 btfTypeVlenShift = 0 70 btfTypeVlenMask = 16 71 btfTypeKindFlagShift = 31 72 btfTypeKindFlagMask = 1 73 ) 74 75 var btfHeaderLen = binary.Size(&btfHeader{}) 76 77 type btfHeader struct { 78 Magic uint16 79 Version uint8 80 Flags uint8 81 HdrLen uint32 82 83 TypeOff uint32 84 TypeLen uint32 85 StringOff uint32 86 StringLen uint32 87 } 88 89 // typeStart returns the offset from the beginning of the .BTF section 90 // to the start of its type entries. 91 func (h *btfHeader) typeStart() int64 { 92 return int64(h.HdrLen + h.TypeOff) 93 } 94 95 // stringStart returns the offset from the beginning of the .BTF section 96 // to the start of its string table. 97 func (h *btfHeader) stringStart() int64 { 98 return int64(h.HdrLen + h.StringOff) 99 } 100 101 // parseBTFHeader parses the header of the .BTF section. 102 func parseBTFHeader(r io.Reader, bo binary.ByteOrder) (*btfHeader, error) { 103 var header btfHeader 104 if err := binary.Read(r, bo, &header); err != nil { 105 return nil, fmt.Errorf("can't read header: %v", err) 106 } 107 108 if header.Magic != btfMagic { 109 return nil, fmt.Errorf("incorrect magic value %v", header.Magic) 110 } 111 112 if header.Version != 1 { 113 return nil, fmt.Errorf("unexpected version %v", header.Version) 114 } 115 116 if header.Flags != 0 { 117 return nil, fmt.Errorf("unsupported flags %v", header.Flags) 118 } 119 120 remainder := int64(header.HdrLen) - int64(binary.Size(&header)) 121 if remainder < 0 { 122 return nil, errors.New("header length shorter than btfHeader size") 123 } 124 125 if _, err := io.CopyN(internal.DiscardZeroes{}, r, remainder); err != nil { 126 return nil, fmt.Errorf("header padding: %v", err) 127 } 128 129 return &header, nil 130 } 131 132 var btfTypeLen = binary.Size(btfType{}) 133 134 // btfType is equivalent to struct btf_type in Documentation/bpf/btf.rst. 135 type btfType struct { 136 NameOff uint32 137 /* "info" bits arrangement 138 * bits 0-15: vlen (e.g. # of struct's members), linkage 139 * bits 16-23: unused 140 * bits 24-28: kind (e.g. int, ptr, array...etc) 141 * bits 29-30: unused 142 * bit 31: kind_flag, currently used by 143 * struct, union and fwd 144 */ 145 Info uint32 146 /* "size" is used by INT, ENUM, STRUCT and UNION. 147 * "size" tells the size of the type it is describing. 148 * 149 * "type" is used by PTR, TYPEDEF, VOLATILE, CONST, RESTRICT, 150 * FUNC and FUNC_PROTO. 151 * "type" is a type_id referring to another type. 152 */ 153 SizeType uint32 154 } 155 156 var btfTypeSize = int(unsafe.Sizeof(btfType{})) 157 158 func unmarshalBtfType(bt *btfType, b []byte, bo binary.ByteOrder) (int, error) { 159 if len(b) < btfTypeSize { 160 return 0, fmt.Errorf("not enough bytes to unmarshal btfType") 161 } 162 163 bt.NameOff = bo.Uint32(b[0:]) 164 bt.Info = bo.Uint32(b[4:]) 165 bt.SizeType = bo.Uint32(b[8:]) 166 return btfTypeSize, nil 167 } 168 169 func mask(len uint32) uint32 { 170 return (1 << len) - 1 171 } 172 173 func readBits(value, len, shift uint32) uint32 { 174 return (value >> shift) & mask(len) 175 } 176 177 func writeBits(value, len, shift, new uint32) uint32 { 178 value &^= mask(len) << shift 179 value |= (new & mask(len)) << shift 180 return value 181 } 182 183 func (bt *btfType) info(len, shift uint32) uint32 { 184 return readBits(bt.Info, len, shift) 185 } 186 187 func (bt *btfType) setInfo(value, len, shift uint32) { 188 bt.Info = writeBits(bt.Info, len, shift, value) 189 } 190 191 func (bt *btfType) Kind() btfKind { 192 return btfKind(bt.info(btfTypeKindLen, btfTypeKindShift)) 193 } 194 195 func (bt *btfType) SetKind(kind btfKind) { 196 bt.setInfo(uint32(kind), btfTypeKindLen, btfTypeKindShift) 197 } 198 199 func (bt *btfType) Vlen() int { 200 return int(bt.info(btfTypeVlenMask, btfTypeVlenShift)) 201 } 202 203 func (bt *btfType) SetVlen(vlen int) { 204 bt.setInfo(uint32(vlen), btfTypeVlenMask, btfTypeVlenShift) 205 } 206 207 func (bt *btfType) kindFlagBool() bool { 208 return bt.info(btfTypeKindFlagMask, btfTypeKindFlagShift) == 1 209 } 210 211 func (bt *btfType) setKindFlagBool(set bool) { 212 var value uint32 213 if set { 214 value = 1 215 } 216 bt.setInfo(value, btfTypeKindFlagMask, btfTypeKindFlagShift) 217 } 218 219 // Bitfield returns true if the struct or union contain a bitfield. 220 func (bt *btfType) Bitfield() bool { 221 return bt.kindFlagBool() 222 } 223 224 func (bt *btfType) SetBitfield(isBitfield bool) { 225 bt.setKindFlagBool(isBitfield) 226 } 227 228 func (bt *btfType) FwdKind() FwdKind { 229 return FwdKind(bt.info(btfTypeKindFlagMask, btfTypeKindFlagShift)) 230 } 231 232 func (bt *btfType) SetFwdKind(kind FwdKind) { 233 bt.setInfo(uint32(kind), btfTypeKindFlagMask, btfTypeKindFlagShift) 234 } 235 236 func (bt *btfType) Signed() bool { 237 return bt.kindFlagBool() 238 } 239 240 func (bt *btfType) SetSigned(signed bool) { 241 bt.setKindFlagBool(signed) 242 } 243 244 func (bt *btfType) Linkage() FuncLinkage { 245 return FuncLinkage(bt.info(btfTypeVlenMask, btfTypeVlenShift)) 246 } 247 248 func (bt *btfType) SetLinkage(linkage FuncLinkage) { 249 bt.setInfo(uint32(linkage), btfTypeVlenMask, btfTypeVlenShift) 250 } 251 252 func (bt *btfType) Type() TypeID { 253 // TODO: Panic here if wrong kind? 254 return TypeID(bt.SizeType) 255 } 256 257 func (bt *btfType) SetType(id TypeID) { 258 bt.SizeType = uint32(id) 259 } 260 261 func (bt *btfType) Size() uint32 { 262 // TODO: Panic here if wrong kind? 263 return bt.SizeType 264 } 265 266 func (bt *btfType) SetSize(size uint32) { 267 bt.SizeType = size 268 } 269 270 func (bt *btfType) Marshal(w io.Writer, bo binary.ByteOrder) error { 271 buf := make([]byte, unsafe.Sizeof(*bt)) 272 bo.PutUint32(buf[0:], bt.NameOff) 273 bo.PutUint32(buf[4:], bt.Info) 274 bo.PutUint32(buf[8:], bt.SizeType) 275 _, err := w.Write(buf) 276 return err 277 } 278 279 type rawType struct { 280 btfType 281 data interface{} 282 } 283 284 func (rt *rawType) Marshal(w io.Writer, bo binary.ByteOrder) error { 285 if err := rt.btfType.Marshal(w, bo); err != nil { 286 return err 287 } 288 289 if rt.data == nil { 290 return nil 291 } 292 293 return binary.Write(w, bo, rt.data) 294 } 295 296 // btfInt encodes additional data for integers. 297 // 298 // ? ? ? ? e e e e o o o o o o o o ? ? ? ? ? ? ? ? b b b b b b b b 299 // ? = undefined 300 // e = encoding 301 // o = offset (bitfields?) 302 // b = bits (bitfields) 303 type btfInt struct { 304 Raw uint32 305 } 306 307 const ( 308 btfIntEncodingLen = 4 309 btfIntEncodingShift = 24 310 btfIntOffsetLen = 8 311 btfIntOffsetShift = 16 312 btfIntBitsLen = 8 313 btfIntBitsShift = 0 314 ) 315 316 var btfIntLen = int(unsafe.Sizeof(btfInt{})) 317 318 func unmarshalBtfInt(bi *btfInt, b []byte, bo binary.ByteOrder) (int, error) { 319 if len(b) < btfIntLen { 320 return 0, fmt.Errorf("not enough bytes to unmarshal btfInt") 321 } 322 323 bi.Raw = bo.Uint32(b[0:]) 324 return btfIntLen, nil 325 } 326 327 func (bi btfInt) Encoding() IntEncoding { 328 return IntEncoding(readBits(bi.Raw, btfIntEncodingLen, btfIntEncodingShift)) 329 } 330 331 func (bi *btfInt) SetEncoding(e IntEncoding) { 332 bi.Raw = writeBits(uint32(bi.Raw), btfIntEncodingLen, btfIntEncodingShift, uint32(e)) 333 } 334 335 func (bi btfInt) Offset() Bits { 336 return Bits(readBits(bi.Raw, btfIntOffsetLen, btfIntOffsetShift)) 337 } 338 339 func (bi *btfInt) SetOffset(offset uint32) { 340 bi.Raw = writeBits(bi.Raw, btfIntOffsetLen, btfIntOffsetShift, offset) 341 } 342 343 func (bi btfInt) Bits() Bits { 344 return Bits(readBits(bi.Raw, btfIntBitsLen, btfIntBitsShift)) 345 } 346 347 func (bi *btfInt) SetBits(bits byte) { 348 bi.Raw = writeBits(bi.Raw, btfIntBitsLen, btfIntBitsShift, uint32(bits)) 349 } 350 351 type btfArray struct { 352 Type TypeID 353 IndexType TypeID 354 Nelems uint32 355 } 356 357 var btfArrayLen = int(unsafe.Sizeof(btfArray{})) 358 359 func unmarshalBtfArray(ba *btfArray, b []byte, bo binary.ByteOrder) (int, error) { 360 if len(b) < btfArrayLen { 361 return 0, fmt.Errorf("not enough bytes to unmarshal btfArray") 362 } 363 364 ba.Type = TypeID(bo.Uint32(b[0:])) 365 ba.IndexType = TypeID(bo.Uint32(b[4:])) 366 ba.Nelems = bo.Uint32(b[8:]) 367 return btfArrayLen, nil 368 } 369 370 type btfMember struct { 371 NameOff uint32 372 Type TypeID 373 Offset uint32 374 } 375 376 var btfMemberLen = int(unsafe.Sizeof(btfMember{})) 377 378 func unmarshalBtfMembers(members []btfMember, b []byte, bo binary.ByteOrder) (int, error) { 379 off := 0 380 for i := range members { 381 if off+btfMemberLen > len(b) { 382 return 0, fmt.Errorf("not enough bytes to unmarshal btfMember %d", i) 383 } 384 385 members[i].NameOff = bo.Uint32(b[off+0:]) 386 members[i].Type = TypeID(bo.Uint32(b[off+4:])) 387 members[i].Offset = bo.Uint32(b[off+8:]) 388 389 off += btfMemberLen 390 } 391 392 return off, nil 393 } 394 395 type btfVarSecinfo struct { 396 Type TypeID 397 Offset uint32 398 Size uint32 399 } 400 401 var btfVarSecinfoLen = int(unsafe.Sizeof(btfVarSecinfo{})) 402 403 func unmarshalBtfVarSecInfos(secinfos []btfVarSecinfo, b []byte, bo binary.ByteOrder) (int, error) { 404 off := 0 405 for i := range secinfos { 406 if off+btfVarSecinfoLen > len(b) { 407 return 0, fmt.Errorf("not enough bytes to unmarshal btfVarSecinfo %d", i) 408 } 409 410 secinfos[i].Type = TypeID(bo.Uint32(b[off+0:])) 411 secinfos[i].Offset = bo.Uint32(b[off+4:]) 412 secinfos[i].Size = bo.Uint32(b[off+8:]) 413 414 off += btfVarSecinfoLen 415 } 416 417 return off, nil 418 } 419 420 type btfVariable struct { 421 Linkage uint32 422 } 423 424 var btfVariableLen = int(unsafe.Sizeof(btfVariable{})) 425 426 func unmarshalBtfVariable(bv *btfVariable, b []byte, bo binary.ByteOrder) (int, error) { 427 if len(b) < btfVariableLen { 428 return 0, fmt.Errorf("not enough bytes to unmarshal btfVariable") 429 } 430 431 bv.Linkage = bo.Uint32(b[0:]) 432 return btfVariableLen, nil 433 } 434 435 type btfEnum struct { 436 NameOff uint32 437 Val uint32 438 } 439 440 var btfEnumLen = int(unsafe.Sizeof(btfEnum{})) 441 442 func unmarshalBtfEnums(enums []btfEnum, b []byte, bo binary.ByteOrder) (int, error) { 443 off := 0 444 for i := range enums { 445 if off+btfEnumLen > len(b) { 446 return 0, fmt.Errorf("not enough bytes to unmarshal btfEnum %d", i) 447 } 448 449 enums[i].NameOff = bo.Uint32(b[off+0:]) 450 enums[i].Val = bo.Uint32(b[off+4:]) 451 452 off += btfEnumLen 453 } 454 455 return off, nil 456 } 457 458 type btfEnum64 struct { 459 NameOff uint32 460 ValLo32 uint32 461 ValHi32 uint32 462 } 463 464 var btfEnum64Len = int(unsafe.Sizeof(btfEnum64{})) 465 466 func unmarshalBtfEnums64(enums []btfEnum64, b []byte, bo binary.ByteOrder) (int, error) { 467 off := 0 468 for i := range enums { 469 if off+btfEnum64Len > len(b) { 470 return 0, fmt.Errorf("not enough bytes to unmarshal btfEnum64 %d", i) 471 } 472 473 enums[i].NameOff = bo.Uint32(b[off+0:]) 474 enums[i].ValLo32 = bo.Uint32(b[off+4:]) 475 enums[i].ValHi32 = bo.Uint32(b[off+8:]) 476 477 off += btfEnum64Len 478 } 479 480 return off, nil 481 } 482 483 type btfParam struct { 484 NameOff uint32 485 Type TypeID 486 } 487 488 var btfParamLen = int(unsafe.Sizeof(btfParam{})) 489 490 func unmarshalBtfParams(params []btfParam, b []byte, bo binary.ByteOrder) (int, error) { 491 off := 0 492 for i := range params { 493 if off+btfParamLen > len(b) { 494 return 0, fmt.Errorf("not enough bytes to unmarshal btfParam %d", i) 495 } 496 497 params[i].NameOff = bo.Uint32(b[off+0:]) 498 params[i].Type = TypeID(bo.Uint32(b[off+4:])) 499 500 off += btfParamLen 501 } 502 503 return off, nil 504 } 505 506 type btfDeclTag struct { 507 ComponentIdx uint32 508 } 509 510 var btfDeclTagLen = int(unsafe.Sizeof(btfDeclTag{})) 511 512 func unmarshalBtfDeclTag(bdt *btfDeclTag, b []byte, bo binary.ByteOrder) (int, error) { 513 if len(b) < btfDeclTagLen { 514 return 0, fmt.Errorf("not enough bytes to unmarshal btfDeclTag") 515 } 516 517 bdt.ComponentIdx = bo.Uint32(b[0:]) 518 return btfDeclTagLen, nil 519 }