github.com/cilium/ebpf@v0.10.0/btf/types.go (about) 1 package btf 2 3 import ( 4 "fmt" 5 "io" 6 "math" 7 "reflect" 8 "strings" 9 10 "github.com/cilium/ebpf/asm" 11 "github.com/cilium/ebpf/internal" 12 ) 13 14 const maxTypeDepth = 32 15 16 // TypeID identifies a type in a BTF section. 17 type TypeID uint32 18 19 // Type represents a type described by BTF. 20 type Type interface { 21 // Type can be formatted using the %s and %v verbs. %s outputs only the 22 // identity of the type, without any detail. %v outputs additional detail. 23 // 24 // Use the '+' flag to include the address of the type. 25 // 26 // Use the width to specify how many levels of detail to output, for example 27 // %1v will output detail for the root type and a short description of its 28 // children. %2v would output details of the root type and its children 29 // as well as a short description of the grandchildren. 30 fmt.Formatter 31 32 // Name of the type, empty for anonymous types and types that cannot 33 // carry a name, like Void and Pointer. 34 TypeName() string 35 36 // Make a copy of the type, without copying Type members. 37 copy() Type 38 39 // New implementations must update walkType. 40 } 41 42 var ( 43 _ Type = (*Int)(nil) 44 _ Type = (*Struct)(nil) 45 _ Type = (*Union)(nil) 46 _ Type = (*Enum)(nil) 47 _ Type = (*Fwd)(nil) 48 _ Type = (*Func)(nil) 49 _ Type = (*Typedef)(nil) 50 _ Type = (*Var)(nil) 51 _ Type = (*Datasec)(nil) 52 _ Type = (*Float)(nil) 53 _ Type = (*declTag)(nil) 54 _ Type = (*typeTag)(nil) 55 _ Type = (*cycle)(nil) 56 ) 57 58 // types is a list of Type. 59 // 60 // The order determines the ID of a type. 61 type types []Type 62 63 func (ts types) ByID(id TypeID) (Type, error) { 64 if int(id) > len(ts) { 65 return nil, fmt.Errorf("type ID %d: %w", id, ErrNotFound) 66 } 67 return ts[id], nil 68 } 69 70 // Void is the unit type of BTF. 71 type Void struct{} 72 73 func (v *Void) Format(fs fmt.State, verb rune) { formatType(fs, verb, v) } 74 func (v *Void) TypeName() string { return "" } 75 func (v *Void) size() uint32 { return 0 } 76 func (v *Void) copy() Type { return (*Void)(nil) } 77 78 type IntEncoding byte 79 80 // Valid IntEncodings. 81 // 82 // These may look like they are flags, but they aren't. 83 const ( 84 Unsigned IntEncoding = 0 85 Signed IntEncoding = 1 86 Char IntEncoding = 2 87 Bool IntEncoding = 4 88 ) 89 90 func (ie IntEncoding) String() string { 91 switch ie { 92 case Char: 93 // NB: There is no way to determine signedness for char. 94 return "char" 95 case Bool: 96 return "bool" 97 case Signed: 98 return "signed" 99 case Unsigned: 100 return "unsigned" 101 default: 102 return fmt.Sprintf("IntEncoding(%d)", byte(ie)) 103 } 104 } 105 106 // Int is an integer of a given length. 107 // 108 // See https://www.kernel.org/doc/html/latest/bpf/btf.html#btf-kind-int 109 type Int struct { 110 Name string 111 112 // The size of the integer in bytes. 113 Size uint32 114 Encoding IntEncoding 115 } 116 117 func (i *Int) Format(fs fmt.State, verb rune) { 118 formatType(fs, verb, i, i.Encoding, "size=", i.Size*8) 119 } 120 121 func (i *Int) TypeName() string { return i.Name } 122 func (i *Int) size() uint32 { return i.Size } 123 func (i *Int) copy() Type { 124 cpy := *i 125 return &cpy 126 } 127 128 // Pointer is a pointer to another type. 129 type Pointer struct { 130 Target Type 131 } 132 133 func (p *Pointer) Format(fs fmt.State, verb rune) { 134 formatType(fs, verb, p, "target=", p.Target) 135 } 136 137 func (p *Pointer) TypeName() string { return "" } 138 func (p *Pointer) size() uint32 { return 8 } 139 func (p *Pointer) copy() Type { 140 cpy := *p 141 return &cpy 142 } 143 144 // Array is an array with a fixed number of elements. 145 type Array struct { 146 Index Type 147 Type Type 148 Nelems uint32 149 } 150 151 func (arr *Array) Format(fs fmt.State, verb rune) { 152 formatType(fs, verb, arr, "index=", arr.Index, "type=", arr.Type, "n=", arr.Nelems) 153 } 154 155 func (arr *Array) TypeName() string { return "" } 156 157 func (arr *Array) copy() Type { 158 cpy := *arr 159 return &cpy 160 } 161 162 // Struct is a compound type of consecutive members. 163 type Struct struct { 164 Name string 165 // The size of the struct including padding, in bytes 166 Size uint32 167 Members []Member 168 } 169 170 func (s *Struct) Format(fs fmt.State, verb rune) { 171 formatType(fs, verb, s, "fields=", len(s.Members)) 172 } 173 174 func (s *Struct) TypeName() string { return s.Name } 175 176 func (s *Struct) size() uint32 { return s.Size } 177 178 func (s *Struct) copy() Type { 179 cpy := *s 180 cpy.Members = copyMembers(s.Members) 181 return &cpy 182 } 183 184 func (s *Struct) members() []Member { 185 return s.Members 186 } 187 188 // Union is a compound type where members occupy the same memory. 189 type Union struct { 190 Name string 191 // The size of the union including padding, in bytes. 192 Size uint32 193 Members []Member 194 } 195 196 func (u *Union) Format(fs fmt.State, verb rune) { 197 formatType(fs, verb, u, "fields=", len(u.Members)) 198 } 199 200 func (u *Union) TypeName() string { return u.Name } 201 202 func (u *Union) size() uint32 { return u.Size } 203 204 func (u *Union) copy() Type { 205 cpy := *u 206 cpy.Members = copyMembers(u.Members) 207 return &cpy 208 } 209 210 func (u *Union) members() []Member { 211 return u.Members 212 } 213 214 func copyMembers(orig []Member) []Member { 215 cpy := make([]Member, len(orig)) 216 copy(cpy, orig) 217 return cpy 218 } 219 220 type composite interface { 221 members() []Member 222 } 223 224 var ( 225 _ composite = (*Struct)(nil) 226 _ composite = (*Union)(nil) 227 ) 228 229 // A value in bits. 230 type Bits uint32 231 232 // Bytes converts a bit value into bytes. 233 func (b Bits) Bytes() uint32 { 234 return uint32(b / 8) 235 } 236 237 // Member is part of a Struct or Union. 238 // 239 // It is not a valid Type. 240 type Member struct { 241 Name string 242 Type Type 243 Offset Bits 244 BitfieldSize Bits 245 } 246 247 // Enum lists possible values. 248 type Enum struct { 249 Name string 250 // Size of the enum value in bytes. 251 Size uint32 252 // True if the values should be interpreted as signed integers. 253 Signed bool 254 Values []EnumValue 255 } 256 257 func (e *Enum) Format(fs fmt.State, verb rune) { 258 formatType(fs, verb, e, "size=", e.Size, "values=", len(e.Values)) 259 } 260 261 func (e *Enum) TypeName() string { return e.Name } 262 263 // EnumValue is part of an Enum 264 // 265 // Is is not a valid Type 266 type EnumValue struct { 267 Name string 268 Value uint64 269 } 270 271 func (e *Enum) size() uint32 { return e.Size } 272 func (e *Enum) copy() Type { 273 cpy := *e 274 cpy.Values = make([]EnumValue, len(e.Values)) 275 copy(cpy.Values, e.Values) 276 return &cpy 277 } 278 279 // has64BitValues returns true if the Enum contains a value larger than 32 bits. 280 // Kernels before 6.0 have enum values that overrun u32 replaced with zeroes. 281 // 282 // 64-bit enums have their Enum.Size attributes correctly set to 8, but if we 283 // use the size attribute as a heuristic during BTF marshaling, we'll emit 284 // ENUM64s to kernels that don't support them. 285 func (e *Enum) has64BitValues() bool { 286 for _, v := range e.Values { 287 if v.Value > math.MaxUint32 { 288 return true 289 } 290 } 291 return false 292 } 293 294 // FwdKind is the type of forward declaration. 295 type FwdKind int 296 297 // Valid types of forward declaration. 298 const ( 299 FwdStruct FwdKind = iota 300 FwdUnion 301 ) 302 303 func (fk FwdKind) String() string { 304 switch fk { 305 case FwdStruct: 306 return "struct" 307 case FwdUnion: 308 return "union" 309 default: 310 return fmt.Sprintf("%T(%d)", fk, int(fk)) 311 } 312 } 313 314 // Fwd is a forward declaration of a Type. 315 type Fwd struct { 316 Name string 317 Kind FwdKind 318 } 319 320 func (f *Fwd) Format(fs fmt.State, verb rune) { 321 formatType(fs, verb, f, f.Kind) 322 } 323 324 func (f *Fwd) TypeName() string { return f.Name } 325 326 func (f *Fwd) copy() Type { 327 cpy := *f 328 return &cpy 329 } 330 331 // Typedef is an alias of a Type. 332 type Typedef struct { 333 Name string 334 Type Type 335 } 336 337 func (td *Typedef) Format(fs fmt.State, verb rune) { 338 formatType(fs, verb, td, td.Type) 339 } 340 341 func (td *Typedef) TypeName() string { return td.Name } 342 343 func (td *Typedef) copy() Type { 344 cpy := *td 345 return &cpy 346 } 347 348 // Volatile is a qualifier. 349 type Volatile struct { 350 Type Type 351 } 352 353 func (v *Volatile) Format(fs fmt.State, verb rune) { 354 formatType(fs, verb, v, v.Type) 355 } 356 357 func (v *Volatile) TypeName() string { return "" } 358 359 func (v *Volatile) qualify() Type { return v.Type } 360 func (v *Volatile) copy() Type { 361 cpy := *v 362 return &cpy 363 } 364 365 // Const is a qualifier. 366 type Const struct { 367 Type Type 368 } 369 370 func (c *Const) Format(fs fmt.State, verb rune) { 371 formatType(fs, verb, c, c.Type) 372 } 373 374 func (c *Const) TypeName() string { return "" } 375 376 func (c *Const) qualify() Type { return c.Type } 377 func (c *Const) copy() Type { 378 cpy := *c 379 return &cpy 380 } 381 382 // Restrict is a qualifier. 383 type Restrict struct { 384 Type Type 385 } 386 387 func (r *Restrict) Format(fs fmt.State, verb rune) { 388 formatType(fs, verb, r, r.Type) 389 } 390 391 func (r *Restrict) TypeName() string { return "" } 392 393 func (r *Restrict) qualify() Type { return r.Type } 394 func (r *Restrict) copy() Type { 395 cpy := *r 396 return &cpy 397 } 398 399 // Func is a function definition. 400 type Func struct { 401 Name string 402 Type Type 403 Linkage FuncLinkage 404 } 405 406 func FuncMetadata(ins *asm.Instruction) *Func { 407 fn, _ := ins.Metadata.Get(funcInfoMeta{}).(*Func) 408 return fn 409 } 410 411 // WithFuncMetadata adds a btf.Func to the Metadata of asm.Instruction. 412 func WithFuncMetadata(ins asm.Instruction, fn *Func) asm.Instruction { 413 ins.Metadata.Set(funcInfoMeta{}, fn) 414 return ins 415 } 416 417 func (f *Func) Format(fs fmt.State, verb rune) { 418 formatType(fs, verb, f, f.Linkage, "proto=", f.Type) 419 } 420 421 func (f *Func) TypeName() string { return f.Name } 422 423 func (f *Func) copy() Type { 424 cpy := *f 425 return &cpy 426 } 427 428 // FuncProto is a function declaration. 429 type FuncProto struct { 430 Return Type 431 Params []FuncParam 432 } 433 434 func (fp *FuncProto) Format(fs fmt.State, verb rune) { 435 formatType(fs, verb, fp, "args=", len(fp.Params), "return=", fp.Return) 436 } 437 438 func (fp *FuncProto) TypeName() string { return "" } 439 440 func (fp *FuncProto) copy() Type { 441 cpy := *fp 442 cpy.Params = make([]FuncParam, len(fp.Params)) 443 copy(cpy.Params, fp.Params) 444 return &cpy 445 } 446 447 type FuncParam struct { 448 Name string 449 Type Type 450 } 451 452 // Var is a global variable. 453 type Var struct { 454 Name string 455 Type Type 456 Linkage VarLinkage 457 } 458 459 func (v *Var) Format(fs fmt.State, verb rune) { 460 formatType(fs, verb, v, v.Linkage) 461 } 462 463 func (v *Var) TypeName() string { return v.Name } 464 465 func (v *Var) copy() Type { 466 cpy := *v 467 return &cpy 468 } 469 470 // Datasec is a global program section containing data. 471 type Datasec struct { 472 Name string 473 Size uint32 474 Vars []VarSecinfo 475 } 476 477 func (ds *Datasec) Format(fs fmt.State, verb rune) { 478 formatType(fs, verb, ds) 479 } 480 481 func (ds *Datasec) TypeName() string { return ds.Name } 482 483 func (ds *Datasec) size() uint32 { return ds.Size } 484 485 func (ds *Datasec) copy() Type { 486 cpy := *ds 487 cpy.Vars = make([]VarSecinfo, len(ds.Vars)) 488 copy(cpy.Vars, ds.Vars) 489 return &cpy 490 } 491 492 // VarSecinfo describes variable in a Datasec. 493 // 494 // It is not a valid Type. 495 type VarSecinfo struct { 496 // Var or Func. 497 Type Type 498 Offset uint32 499 Size uint32 500 } 501 502 // Float is a float of a given length. 503 type Float struct { 504 Name string 505 506 // The size of the float in bytes. 507 Size uint32 508 } 509 510 func (f *Float) Format(fs fmt.State, verb rune) { 511 formatType(fs, verb, f, "size=", f.Size*8) 512 } 513 514 func (f *Float) TypeName() string { return f.Name } 515 func (f *Float) size() uint32 { return f.Size } 516 func (f *Float) copy() Type { 517 cpy := *f 518 return &cpy 519 } 520 521 // declTag associates metadata with a declaration. 522 type declTag struct { 523 Type Type 524 Value string 525 // The index this tag refers to in the target type. For composite types, 526 // a value of -1 indicates that the tag refers to the whole type. Otherwise 527 // it indicates which member or argument the tag applies to. 528 Index int 529 } 530 531 func (dt *declTag) Format(fs fmt.State, verb rune) { 532 formatType(fs, verb, dt, "type=", dt.Type, "value=", dt.Value, "index=", dt.Index) 533 } 534 535 func (dt *declTag) TypeName() string { return "" } 536 func (dt *declTag) copy() Type { 537 cpy := *dt 538 return &cpy 539 } 540 541 // typeTag associates metadata with a type. 542 type typeTag struct { 543 Type Type 544 Value string 545 } 546 547 func (tt *typeTag) Format(fs fmt.State, verb rune) { 548 formatType(fs, verb, tt, "type=", tt.Type, "value=", tt.Value) 549 } 550 551 func (tt *typeTag) TypeName() string { return "" } 552 func (tt *typeTag) qualify() Type { return tt.Type } 553 func (tt *typeTag) copy() Type { 554 cpy := *tt 555 return &cpy 556 } 557 558 // cycle is a type which had to be elided since it exceeded maxTypeDepth. 559 type cycle struct { 560 root Type 561 } 562 563 func (c *cycle) ID() TypeID { return math.MaxUint32 } 564 func (c *cycle) Format(fs fmt.State, verb rune) { formatType(fs, verb, c, "root=", c.root) } 565 func (c *cycle) TypeName() string { return "" } 566 func (c *cycle) copy() Type { 567 cpy := *c 568 return &cpy 569 } 570 571 type sizer interface { 572 size() uint32 573 } 574 575 var ( 576 _ sizer = (*Int)(nil) 577 _ sizer = (*Pointer)(nil) 578 _ sizer = (*Struct)(nil) 579 _ sizer = (*Union)(nil) 580 _ sizer = (*Enum)(nil) 581 _ sizer = (*Datasec)(nil) 582 ) 583 584 type qualifier interface { 585 qualify() Type 586 } 587 588 var ( 589 _ qualifier = (*Const)(nil) 590 _ qualifier = (*Restrict)(nil) 591 _ qualifier = (*Volatile)(nil) 592 _ qualifier = (*typeTag)(nil) 593 ) 594 595 // Sizeof returns the size of a type in bytes. 596 // 597 // Returns an error if the size can't be computed. 598 func Sizeof(typ Type) (int, error) { 599 var ( 600 n = int64(1) 601 elem int64 602 ) 603 604 for i := 0; i < maxTypeDepth; i++ { 605 switch v := typ.(type) { 606 case *Array: 607 if n > 0 && int64(v.Nelems) > math.MaxInt64/n { 608 return 0, fmt.Errorf("type %s: overflow", typ) 609 } 610 611 // Arrays may be of zero length, which allows 612 // n to be zero as well. 613 n *= int64(v.Nelems) 614 typ = v.Type 615 continue 616 617 case sizer: 618 elem = int64(v.size()) 619 620 case *Typedef: 621 typ = v.Type 622 continue 623 624 case qualifier: 625 typ = v.qualify() 626 continue 627 628 default: 629 return 0, fmt.Errorf("unsized type %T", typ) 630 } 631 632 if n > 0 && elem > math.MaxInt64/n { 633 return 0, fmt.Errorf("type %s: overflow", typ) 634 } 635 636 size := n * elem 637 if int64(int(size)) != size { 638 return 0, fmt.Errorf("type %s: overflow", typ) 639 } 640 641 return int(size), nil 642 } 643 644 return 0, fmt.Errorf("type %s: exceeded type depth", typ) 645 } 646 647 // alignof returns the alignment of a type. 648 // 649 // Currently only supports the subset of types necessary for bitfield relocations. 650 func alignof(typ Type) (int, error) { 651 switch t := UnderlyingType(typ).(type) { 652 case *Enum: 653 return int(t.size()), nil 654 case *Int: 655 return int(t.Size), nil 656 default: 657 return 0, fmt.Errorf("can't calculate alignment of %T", t) 658 } 659 } 660 661 // Transformer modifies a given Type and returns the result. 662 // 663 // For example, UnderlyingType removes any qualifiers or typedefs from a type. 664 // See the example on Copy for how to use a transform. 665 type Transformer func(Type) Type 666 667 // Copy a Type recursively. 668 // 669 // typ may form a cycle. If transform is not nil, it is called with the 670 // to be copied type, and the returned value is copied instead. 671 func Copy(typ Type, transform Transformer) Type { 672 copies := make(copier) 673 copies.copy(&typ, transform) 674 return typ 675 } 676 677 // copy a slice of Types recursively. 678 // 679 // See Copy for the semantics. 680 func copyTypes(types []Type, transform Transformer) []Type { 681 result := make([]Type, len(types)) 682 copy(result, types) 683 684 copies := make(copier) 685 for i := range result { 686 copies.copy(&result[i], transform) 687 } 688 689 return result 690 } 691 692 type copier map[Type]Type 693 694 func (c copier) copy(typ *Type, transform Transformer) { 695 var work typeDeque 696 for t := typ; t != nil; t = work.Pop() { 697 // *t is the identity of the type. 698 if cpy := c[*t]; cpy != nil { 699 *t = cpy 700 continue 701 } 702 703 var cpy Type 704 if transform != nil { 705 cpy = transform(*t).copy() 706 } else { 707 cpy = (*t).copy() 708 } 709 710 c[*t] = cpy 711 *t = cpy 712 713 // Mark any nested types for copying. 714 walkType(cpy, work.Push) 715 } 716 } 717 718 type typeDeque = internal.Deque[*Type] 719 720 // inflateRawTypes takes a list of raw btf types linked via type IDs, and turns 721 // it into a graph of Types connected via pointers. 722 // 723 // If baseTypes are provided, then the raw types are 724 // considered to be of a split BTF (e.g., a kernel module). 725 // 726 // Returns a slice of types indexed by TypeID. Since BTF ignores compilation 727 // units, multiple types may share the same name. A Type may form a cyclic graph 728 // by pointing at itself. 729 func inflateRawTypes(rawTypes []rawType, baseTypes types, rawStrings *stringTable) ([]Type, error) { 730 types := make([]Type, 0, len(rawTypes)+1) // +1 for Void added to base types 731 732 typeIDOffset := TypeID(1) // Void is TypeID(0), so the rest starts from TypeID(1) 733 734 if baseTypes == nil { 735 // Void is defined to always be type ID 0, and is thus omitted from BTF. 736 types = append(types, (*Void)(nil)) 737 } else { 738 // For split BTF, the next ID is max base BTF type ID + 1 739 typeIDOffset = TypeID(len(baseTypes)) 740 } 741 742 type fixupDef struct { 743 id TypeID 744 typ *Type 745 } 746 747 var fixups []fixupDef 748 fixup := func(id TypeID, typ *Type) bool { 749 if id < TypeID(len(baseTypes)) { 750 *typ = baseTypes[id] 751 return true 752 } 753 754 idx := id 755 if baseTypes != nil { 756 idx = id - TypeID(len(baseTypes)) 757 } 758 if idx < TypeID(len(types)) { 759 // We've already inflated this type, fix it up immediately. 760 *typ = types[idx] 761 return true 762 } 763 fixups = append(fixups, fixupDef{id, typ}) 764 return false 765 } 766 767 type assertion struct { 768 id TypeID 769 typ *Type 770 want reflect.Type 771 } 772 773 var assertions []assertion 774 fixupAndAssert := func(id TypeID, typ *Type, want reflect.Type) error { 775 if !fixup(id, typ) { 776 assertions = append(assertions, assertion{id, typ, want}) 777 return nil 778 } 779 780 // The type has already been fixed up, check the type immediately. 781 if reflect.TypeOf(*typ) != want { 782 return fmt.Errorf("type ID %d: expected %s, got %T", id, want, *typ) 783 } 784 return nil 785 } 786 787 type bitfieldFixupDef struct { 788 id TypeID 789 m *Member 790 } 791 792 var ( 793 legacyBitfields = make(map[TypeID][2]Bits) // offset, size 794 bitfieldFixups []bitfieldFixupDef 795 ) 796 convertMembers := func(raw []btfMember, kindFlag bool) ([]Member, error) { 797 // NB: The fixup below relies on pre-allocating this array to 798 // work, since otherwise append might re-allocate members. 799 members := make([]Member, 0, len(raw)) 800 for i, btfMember := range raw { 801 name, err := rawStrings.Lookup(btfMember.NameOff) 802 if err != nil { 803 return nil, fmt.Errorf("can't get name for member %d: %w", i, err) 804 } 805 806 members = append(members, Member{ 807 Name: name, 808 Offset: Bits(btfMember.Offset), 809 }) 810 811 m := &members[i] 812 fixup(raw[i].Type, &m.Type) 813 814 if kindFlag { 815 m.BitfieldSize = Bits(btfMember.Offset >> 24) 816 m.Offset &= 0xffffff 817 // We ignore legacy bitfield definitions if the current composite 818 // is a new-style bitfield. This is kind of safe since offset and 819 // size on the type of the member must be zero if kindFlat is set 820 // according to spec. 821 continue 822 } 823 824 // This may be a legacy bitfield, try to fix it up. 825 data, ok := legacyBitfields[raw[i].Type] 826 if ok { 827 // Bingo! 828 m.Offset += data[0] 829 m.BitfieldSize = data[1] 830 continue 831 } 832 833 if m.Type != nil { 834 // We couldn't find a legacy bitfield, but we know that the member's 835 // type has already been inflated. Hence we know that it can't be 836 // a legacy bitfield and there is nothing left to do. 837 continue 838 } 839 840 // We don't have fixup data, and the type we're pointing 841 // at hasn't been inflated yet. No choice but to defer 842 // the fixup. 843 bitfieldFixups = append(bitfieldFixups, bitfieldFixupDef{ 844 raw[i].Type, 845 m, 846 }) 847 } 848 return members, nil 849 } 850 851 var declTags []*declTag 852 for i, raw := range rawTypes { 853 var ( 854 id = typeIDOffset + TypeID(i) 855 typ Type 856 ) 857 858 name, err := rawStrings.Lookup(raw.NameOff) 859 if err != nil { 860 return nil, fmt.Errorf("get name for type id %d: %w", id, err) 861 } 862 863 switch raw.Kind() { 864 case kindInt: 865 size := raw.Size() 866 bi := raw.data.(*btfInt) 867 if bi.Offset() > 0 || bi.Bits().Bytes() != size { 868 legacyBitfields[id] = [2]Bits{bi.Offset(), bi.Bits()} 869 } 870 typ = &Int{name, raw.Size(), bi.Encoding()} 871 872 case kindPointer: 873 ptr := &Pointer{nil} 874 fixup(raw.Type(), &ptr.Target) 875 typ = ptr 876 877 case kindArray: 878 btfArr := raw.data.(*btfArray) 879 arr := &Array{nil, nil, btfArr.Nelems} 880 fixup(btfArr.IndexType, &arr.Index) 881 fixup(btfArr.Type, &arr.Type) 882 typ = arr 883 884 case kindStruct: 885 members, err := convertMembers(raw.data.([]btfMember), raw.Bitfield()) 886 if err != nil { 887 return nil, fmt.Errorf("struct %s (id %d): %w", name, id, err) 888 } 889 typ = &Struct{name, raw.Size(), members} 890 891 case kindUnion: 892 members, err := convertMembers(raw.data.([]btfMember), raw.Bitfield()) 893 if err != nil { 894 return nil, fmt.Errorf("union %s (id %d): %w", name, id, err) 895 } 896 typ = &Union{name, raw.Size(), members} 897 898 case kindEnum: 899 rawvals := raw.data.([]btfEnum) 900 vals := make([]EnumValue, 0, len(rawvals)) 901 signed := raw.Signed() 902 for i, btfVal := range rawvals { 903 name, err := rawStrings.Lookup(btfVal.NameOff) 904 if err != nil { 905 return nil, fmt.Errorf("get name for enum value %d: %s", i, err) 906 } 907 value := uint64(btfVal.Val) 908 if signed { 909 // Sign extend values to 64 bit. 910 value = uint64(int32(btfVal.Val)) 911 } 912 vals = append(vals, EnumValue{name, value}) 913 } 914 typ = &Enum{name, raw.Size(), signed, vals} 915 916 case kindForward: 917 typ = &Fwd{name, raw.FwdKind()} 918 919 case kindTypedef: 920 typedef := &Typedef{name, nil} 921 fixup(raw.Type(), &typedef.Type) 922 typ = typedef 923 924 case kindVolatile: 925 volatile := &Volatile{nil} 926 fixup(raw.Type(), &volatile.Type) 927 typ = volatile 928 929 case kindConst: 930 cnst := &Const{nil} 931 fixup(raw.Type(), &cnst.Type) 932 typ = cnst 933 934 case kindRestrict: 935 restrict := &Restrict{nil} 936 fixup(raw.Type(), &restrict.Type) 937 typ = restrict 938 939 case kindFunc: 940 fn := &Func{name, nil, raw.Linkage()} 941 if err := fixupAndAssert(raw.Type(), &fn.Type, reflect.TypeOf((*FuncProto)(nil))); err != nil { 942 return nil, err 943 } 944 typ = fn 945 946 case kindFuncProto: 947 rawparams := raw.data.([]btfParam) 948 params := make([]FuncParam, 0, len(rawparams)) 949 for i, param := range rawparams { 950 name, err := rawStrings.Lookup(param.NameOff) 951 if err != nil { 952 return nil, fmt.Errorf("get name for func proto parameter %d: %s", i, err) 953 } 954 params = append(params, FuncParam{ 955 Name: name, 956 }) 957 } 958 for i := range params { 959 fixup(rawparams[i].Type, ¶ms[i].Type) 960 } 961 962 fp := &FuncProto{nil, params} 963 fixup(raw.Type(), &fp.Return) 964 typ = fp 965 966 case kindVar: 967 variable := raw.data.(*btfVariable) 968 v := &Var{name, nil, VarLinkage(variable.Linkage)} 969 fixup(raw.Type(), &v.Type) 970 typ = v 971 972 case kindDatasec: 973 btfVars := raw.data.([]btfVarSecinfo) 974 vars := make([]VarSecinfo, 0, len(btfVars)) 975 for _, btfVar := range btfVars { 976 vars = append(vars, VarSecinfo{ 977 Offset: btfVar.Offset, 978 Size: btfVar.Size, 979 }) 980 } 981 for i := range vars { 982 fixup(btfVars[i].Type, &vars[i].Type) 983 } 984 typ = &Datasec{name, raw.Size(), vars} 985 986 case kindFloat: 987 typ = &Float{name, raw.Size()} 988 989 case kindDeclTag: 990 btfIndex := raw.data.(*btfDeclTag).ComponentIdx 991 if uint64(btfIndex) > math.MaxInt { 992 return nil, fmt.Errorf("type id %d: index exceeds int", id) 993 } 994 995 dt := &declTag{nil, name, int(int32(btfIndex))} 996 fixup(raw.Type(), &dt.Type) 997 typ = dt 998 999 declTags = append(declTags, dt) 1000 1001 case kindTypeTag: 1002 tt := &typeTag{nil, name} 1003 fixup(raw.Type(), &tt.Type) 1004 typ = tt 1005 1006 case kindEnum64: 1007 rawvals := raw.data.([]btfEnum64) 1008 vals := make([]EnumValue, 0, len(rawvals)) 1009 for i, btfVal := range rawvals { 1010 name, err := rawStrings.Lookup(btfVal.NameOff) 1011 if err != nil { 1012 return nil, fmt.Errorf("get name for enum64 value %d: %s", i, err) 1013 } 1014 value := (uint64(btfVal.ValHi32) << 32) | uint64(btfVal.ValLo32) 1015 vals = append(vals, EnumValue{name, value}) 1016 } 1017 typ = &Enum{name, raw.Size(), raw.Signed(), vals} 1018 1019 default: 1020 return nil, fmt.Errorf("type id %d: unknown kind: %v", id, raw.Kind()) 1021 } 1022 1023 types = append(types, typ) 1024 } 1025 1026 for _, fixup := range fixups { 1027 i := int(fixup.id) 1028 if i >= len(types)+len(baseTypes) { 1029 return nil, fmt.Errorf("reference to invalid type id: %d", fixup.id) 1030 } 1031 if i < len(baseTypes) { 1032 return nil, fmt.Errorf("fixup for base type id %d is not expected", i) 1033 } 1034 1035 *fixup.typ = types[i-len(baseTypes)] 1036 } 1037 1038 for _, bitfieldFixup := range bitfieldFixups { 1039 if bitfieldFixup.id < TypeID(len(baseTypes)) { 1040 return nil, fmt.Errorf("bitfield fixup from split to base types is not expected") 1041 } 1042 1043 data, ok := legacyBitfields[bitfieldFixup.id] 1044 if ok { 1045 // This is indeed a legacy bitfield, fix it up. 1046 bitfieldFixup.m.Offset += data[0] 1047 bitfieldFixup.m.BitfieldSize = data[1] 1048 } 1049 } 1050 1051 for _, assertion := range assertions { 1052 if reflect.TypeOf(*assertion.typ) != assertion.want { 1053 return nil, fmt.Errorf("type ID %d: expected %s, got %T", assertion.id, assertion.want, *assertion.typ) 1054 } 1055 } 1056 1057 for _, dt := range declTags { 1058 switch t := dt.Type.(type) { 1059 case *Var, *Typedef: 1060 if dt.Index != -1 { 1061 return nil, fmt.Errorf("type %s: index %d is not -1", dt, dt.Index) 1062 } 1063 1064 case composite: 1065 if dt.Index >= len(t.members()) { 1066 return nil, fmt.Errorf("type %s: index %d exceeds members of %s", dt, dt.Index, t) 1067 } 1068 1069 case *Func: 1070 if dt.Index >= len(t.Type.(*FuncProto).Params) { 1071 return nil, fmt.Errorf("type %s: index %d exceeds params of %s", dt, dt.Index, t) 1072 } 1073 1074 default: 1075 return nil, fmt.Errorf("type %s: decl tag for type %s is not supported", dt, t) 1076 } 1077 } 1078 1079 return types, nil 1080 } 1081 1082 // essentialName represents the name of a BTF type stripped of any flavor 1083 // suffixes after a ___ delimiter. 1084 type essentialName string 1085 1086 // newEssentialName returns name without a ___ suffix. 1087 // 1088 // CO-RE has the concept of 'struct flavors', which are used to deal with 1089 // changes in kernel data structures. Anything after three underscores 1090 // in a type name is ignored for the purpose of finding a candidate type 1091 // in the kernel's BTF. 1092 func newEssentialName(name string) essentialName { 1093 if name == "" { 1094 return "" 1095 } 1096 lastIdx := strings.LastIndex(name, "___") 1097 if lastIdx > 0 { 1098 return essentialName(name[:lastIdx]) 1099 } 1100 return essentialName(name) 1101 } 1102 1103 // UnderlyingType skips qualifiers and Typedefs. 1104 func UnderlyingType(typ Type) Type { 1105 result := typ 1106 for depth := 0; depth <= maxTypeDepth; depth++ { 1107 switch v := (result).(type) { 1108 case qualifier: 1109 result = v.qualify() 1110 case *Typedef: 1111 result = v.Type 1112 default: 1113 return result 1114 } 1115 } 1116 return &cycle{typ} 1117 } 1118 1119 type formatState struct { 1120 fmt.State 1121 depth int 1122 } 1123 1124 // formattableType is a subset of Type, to ease unit testing of formatType. 1125 type formattableType interface { 1126 fmt.Formatter 1127 TypeName() string 1128 } 1129 1130 // formatType formats a type in a canonical form. 1131 // 1132 // Handles cyclical types by only printing cycles up to a certain depth. Elements 1133 // in extra are separated by spaces unless the preceding element is a string 1134 // ending in '='. 1135 func formatType(f fmt.State, verb rune, t formattableType, extra ...interface{}) { 1136 if verb != 'v' && verb != 's' { 1137 fmt.Fprintf(f, "{UNRECOGNIZED: %c}", verb) 1138 return 1139 } 1140 1141 // This is the same as %T, but elides the package name. Assumes that 1142 // formattableType is implemented by a pointer receiver. 1143 goTypeName := reflect.TypeOf(t).Elem().Name() 1144 _, _ = io.WriteString(f, goTypeName) 1145 1146 if name := t.TypeName(); name != "" { 1147 // Output BTF type name if present. 1148 fmt.Fprintf(f, ":%q", name) 1149 } 1150 1151 if f.Flag('+') { 1152 // Output address if requested. 1153 fmt.Fprintf(f, ":%#p", t) 1154 } 1155 1156 if verb == 's' { 1157 // %s omits details. 1158 return 1159 } 1160 1161 var depth int 1162 if ps, ok := f.(*formatState); ok { 1163 depth = ps.depth 1164 f = ps.State 1165 } 1166 1167 maxDepth, ok := f.Width() 1168 if !ok { 1169 maxDepth = 0 1170 } 1171 1172 if depth > maxDepth { 1173 // We've reached the maximum depth. This avoids infinite recursion even 1174 // for cyclical types. 1175 return 1176 } 1177 1178 if len(extra) == 0 { 1179 return 1180 } 1181 1182 wantSpace := false 1183 _, _ = io.WriteString(f, "[") 1184 for _, arg := range extra { 1185 if wantSpace { 1186 _, _ = io.WriteString(f, " ") 1187 } 1188 1189 switch v := arg.(type) { 1190 case string: 1191 _, _ = io.WriteString(f, v) 1192 wantSpace = len(v) > 0 && v[len(v)-1] != '=' 1193 continue 1194 1195 case formattableType: 1196 v.Format(&formatState{f, depth + 1}, verb) 1197 1198 default: 1199 fmt.Fprint(f, arg) 1200 } 1201 1202 wantSpace = true 1203 } 1204 _, _ = io.WriteString(f, "]") 1205 }