github.com/cilium/ebpf@v0.16.0/btf/btf.go (about)

     1  package btf
     2  
     3  import (
     4  	"bufio"
     5  	"debug/elf"
     6  	"encoding/binary"
     7  	"errors"
     8  	"fmt"
     9  	"io"
    10  	"math"
    11  	"os"
    12  	"reflect"
    13  	"sync"
    14  
    15  	"github.com/cilium/ebpf/internal"
    16  	"github.com/cilium/ebpf/internal/sys"
    17  )
    18  
    19  const btfMagic = 0xeB9F
    20  
    21  // Errors returned by BTF functions.
    22  var (
    23  	ErrNotSupported    = internal.ErrNotSupported
    24  	ErrNotFound        = errors.New("not found")
    25  	ErrNoExtendedInfo  = errors.New("no extended info")
    26  	ErrMultipleMatches = errors.New("multiple matching types")
    27  )
    28  
    29  // ID represents the unique ID of a BTF object.
    30  type ID = sys.BTFID
    31  
    32  // immutableTypes is a set of types which musn't be changed.
    33  type immutableTypes struct {
    34  	// All types contained by the spec, not including types from the base in
    35  	// case the spec was parsed from split BTF.
    36  	types []Type
    37  
    38  	// Type IDs indexed by type.
    39  	typeIDs map[Type]TypeID
    40  
    41  	// The ID of the first type in types.
    42  	firstTypeID TypeID
    43  
    44  	// Types indexed by essential name.
    45  	// Includes all struct flavors and types with the same name.
    46  	namedTypes map[essentialName][]TypeID
    47  
    48  	// Byte order of the types. This affects things like struct member order
    49  	// when using bitfields.
    50  	byteOrder binary.ByteOrder
    51  }
    52  
    53  func (s *immutableTypes) typeByID(id TypeID) (Type, bool) {
    54  	if id < s.firstTypeID {
    55  		return nil, false
    56  	}
    57  
    58  	index := int(id - s.firstTypeID)
    59  	if index >= len(s.types) {
    60  		return nil, false
    61  	}
    62  
    63  	return s.types[index], true
    64  }
    65  
    66  // mutableTypes is a set of types which may be changed.
    67  type mutableTypes struct {
    68  	imm           immutableTypes
    69  	mu            sync.RWMutex    // protects copies below
    70  	copies        map[Type]Type   // map[orig]copy
    71  	copiedTypeIDs map[Type]TypeID // map[copy]origID
    72  }
    73  
    74  // add a type to the set of mutable types.
    75  //
    76  // Copies type and all of its children once. Repeated calls with the same type
    77  // do not copy again.
    78  func (mt *mutableTypes) add(typ Type, typeIDs map[Type]TypeID) Type {
    79  	mt.mu.RLock()
    80  	cpy, ok := mt.copies[typ]
    81  	mt.mu.RUnlock()
    82  
    83  	if ok {
    84  		// Fast path: the type has been copied before.
    85  		return cpy
    86  	}
    87  
    88  	// modifyGraphPreorder copies the type graph node by node, so we can't drop
    89  	// the lock in between.
    90  	mt.mu.Lock()
    91  	defer mt.mu.Unlock()
    92  
    93  	return copyType(typ, typeIDs, mt.copies, mt.copiedTypeIDs)
    94  }
    95  
    96  // copy a set of mutable types.
    97  func (mt *mutableTypes) copy() *mutableTypes {
    98  	if mt == nil {
    99  		return nil
   100  	}
   101  
   102  	mtCopy := &mutableTypes{
   103  		mt.imm,
   104  		sync.RWMutex{},
   105  		make(map[Type]Type, len(mt.copies)),
   106  		make(map[Type]TypeID, len(mt.copiedTypeIDs)),
   107  	}
   108  
   109  	// Prevent concurrent modification of mt.copiedTypeIDs.
   110  	mt.mu.RLock()
   111  	defer mt.mu.RUnlock()
   112  
   113  	copiesOfCopies := make(map[Type]Type, len(mt.copies))
   114  	for orig, copy := range mt.copies {
   115  		// NB: We make a copy of copy, not orig, so that changes to mutable types
   116  		// are preserved.
   117  		copyOfCopy := copyType(copy, mt.copiedTypeIDs, copiesOfCopies, mtCopy.copiedTypeIDs)
   118  		mtCopy.copies[orig] = copyOfCopy
   119  	}
   120  
   121  	return mtCopy
   122  }
   123  
   124  func (mt *mutableTypes) typeID(typ Type) (TypeID, error) {
   125  	if _, ok := typ.(*Void); ok {
   126  		// Equality is weird for void, since it is a zero sized type.
   127  		return 0, nil
   128  	}
   129  
   130  	mt.mu.RLock()
   131  	defer mt.mu.RUnlock()
   132  
   133  	id, ok := mt.copiedTypeIDs[typ]
   134  	if !ok {
   135  		return 0, fmt.Errorf("no ID for type %s: %w", typ, ErrNotFound)
   136  	}
   137  
   138  	return id, nil
   139  }
   140  
   141  func (mt *mutableTypes) typeByID(id TypeID) (Type, bool) {
   142  	immT, ok := mt.imm.typeByID(id)
   143  	if !ok {
   144  		return nil, false
   145  	}
   146  
   147  	return mt.add(immT, mt.imm.typeIDs), true
   148  }
   149  
   150  func (mt *mutableTypes) anyTypesByName(name string) ([]Type, error) {
   151  	immTypes := mt.imm.namedTypes[newEssentialName(name)]
   152  	if len(immTypes) == 0 {
   153  		return nil, fmt.Errorf("type name %s: %w", name, ErrNotFound)
   154  	}
   155  
   156  	// Return a copy to prevent changes to namedTypes.
   157  	result := make([]Type, 0, len(immTypes))
   158  	for _, id := range immTypes {
   159  		immT, ok := mt.imm.typeByID(id)
   160  		if !ok {
   161  			return nil, fmt.Errorf("no type with ID %d", id)
   162  		}
   163  
   164  		// Match against the full name, not just the essential one
   165  		// in case the type being looked up is a struct flavor.
   166  		if immT.TypeName() == name {
   167  			result = append(result, mt.add(immT, mt.imm.typeIDs))
   168  		}
   169  	}
   170  	return result, nil
   171  }
   172  
   173  // Spec allows querying a set of Types and loading the set into the
   174  // kernel.
   175  type Spec struct {
   176  	*mutableTypes
   177  
   178  	// String table from ELF.
   179  	strings *stringTable
   180  }
   181  
   182  // LoadSpec opens file and calls LoadSpecFromReader on it.
   183  func LoadSpec(file string) (*Spec, error) {
   184  	fh, err := os.Open(file)
   185  	if err != nil {
   186  		return nil, err
   187  	}
   188  	defer fh.Close()
   189  
   190  	return LoadSpecFromReader(fh)
   191  }
   192  
   193  // LoadSpecFromReader reads from an ELF or a raw BTF blob.
   194  //
   195  // Returns ErrNotFound if reading from an ELF which contains no BTF. ExtInfos
   196  // may be nil.
   197  func LoadSpecFromReader(rd io.ReaderAt) (*Spec, error) {
   198  	file, err := internal.NewSafeELFFile(rd)
   199  	if err != nil {
   200  		if bo := guessRawBTFByteOrder(rd); bo != nil {
   201  			return loadRawSpec(io.NewSectionReader(rd, 0, math.MaxInt64), bo, nil)
   202  		}
   203  
   204  		return nil, err
   205  	}
   206  
   207  	return loadSpecFromELF(file)
   208  }
   209  
   210  // LoadSpecAndExtInfosFromReader reads from an ELF.
   211  //
   212  // ExtInfos may be nil if the ELF doesn't contain section metadata.
   213  // Returns ErrNotFound if the ELF contains no BTF.
   214  func LoadSpecAndExtInfosFromReader(rd io.ReaderAt) (*Spec, *ExtInfos, error) {
   215  	file, err := internal.NewSafeELFFile(rd)
   216  	if err != nil {
   217  		return nil, nil, err
   218  	}
   219  
   220  	spec, err := loadSpecFromELF(file)
   221  	if err != nil {
   222  		return nil, nil, err
   223  	}
   224  
   225  	extInfos, err := loadExtInfosFromELF(file, spec)
   226  	if err != nil && !errors.Is(err, ErrNotFound) {
   227  		return nil, nil, err
   228  	}
   229  
   230  	return spec, extInfos, nil
   231  }
   232  
   233  // symbolOffsets extracts all symbols offsets from an ELF and indexes them by
   234  // section and variable name.
   235  //
   236  // References to variables in BTF data sections carry unsigned 32-bit offsets.
   237  // Some ELF symbols (e.g. in vmlinux) may point to virtual memory that is well
   238  // beyond this range. Since these symbols cannot be described by BTF info,
   239  // ignore them here.
   240  func symbolOffsets(file *internal.SafeELFFile) (map[symbol]uint32, error) {
   241  	symbols, err := file.Symbols()
   242  	if err != nil {
   243  		return nil, fmt.Errorf("can't read symbols: %v", err)
   244  	}
   245  
   246  	offsets := make(map[symbol]uint32)
   247  	for _, sym := range symbols {
   248  		if idx := sym.Section; idx >= elf.SHN_LORESERVE && idx <= elf.SHN_HIRESERVE {
   249  			// Ignore things like SHN_ABS
   250  			continue
   251  		}
   252  
   253  		if sym.Value > math.MaxUint32 {
   254  			// VarSecinfo offset is u32, cannot reference symbols in higher regions.
   255  			continue
   256  		}
   257  
   258  		if int(sym.Section) >= len(file.Sections) {
   259  			return nil, fmt.Errorf("symbol %s: invalid section %d", sym.Name, sym.Section)
   260  		}
   261  
   262  		secName := file.Sections[sym.Section].Name
   263  		offsets[symbol{secName, sym.Name}] = uint32(sym.Value)
   264  	}
   265  
   266  	return offsets, nil
   267  }
   268  
   269  func loadSpecFromELF(file *internal.SafeELFFile) (*Spec, error) {
   270  	var (
   271  		btfSection   *elf.Section
   272  		sectionSizes = make(map[string]uint32)
   273  	)
   274  
   275  	for _, sec := range file.Sections {
   276  		switch sec.Name {
   277  		case ".BTF":
   278  			btfSection = sec
   279  		default:
   280  			if sec.Type != elf.SHT_PROGBITS && sec.Type != elf.SHT_NOBITS {
   281  				break
   282  			}
   283  
   284  			if sec.Size > math.MaxUint32 {
   285  				return nil, fmt.Errorf("section %s exceeds maximum size", sec.Name)
   286  			}
   287  
   288  			sectionSizes[sec.Name] = uint32(sec.Size)
   289  		}
   290  	}
   291  
   292  	if btfSection == nil {
   293  		return nil, fmt.Errorf("btf: %w", ErrNotFound)
   294  	}
   295  
   296  	offsets, err := symbolOffsets(file)
   297  	if err != nil {
   298  		return nil, err
   299  	}
   300  
   301  	if btfSection.ReaderAt == nil {
   302  		return nil, fmt.Errorf("compressed BTF is not supported")
   303  	}
   304  
   305  	spec, err := loadRawSpec(btfSection.ReaderAt, file.ByteOrder, nil)
   306  	if err != nil {
   307  		return nil, err
   308  	}
   309  
   310  	err = fixupDatasec(spec.imm.types, sectionSizes, offsets)
   311  	if err != nil {
   312  		return nil, err
   313  	}
   314  
   315  	return spec, nil
   316  }
   317  
   318  func loadRawSpec(btf io.ReaderAt, bo binary.ByteOrder, base *Spec) (*Spec, error) {
   319  	var (
   320  		baseStrings *stringTable
   321  		firstTypeID TypeID
   322  		err         error
   323  	)
   324  
   325  	if base != nil {
   326  		if base.imm.firstTypeID != 0 {
   327  			return nil, fmt.Errorf("can't use split BTF as base")
   328  		}
   329  
   330  		baseStrings = base.strings
   331  
   332  		firstTypeID, err = base.nextTypeID()
   333  		if err != nil {
   334  			return nil, err
   335  		}
   336  	}
   337  
   338  	types, rawStrings, err := parseBTF(btf, bo, baseStrings, base)
   339  	if err != nil {
   340  		return nil, err
   341  	}
   342  
   343  	typeIDs, typesByName := indexTypes(types, firstTypeID)
   344  
   345  	return &Spec{
   346  		&mutableTypes{
   347  			immutableTypes{
   348  				types,
   349  				typeIDs,
   350  				firstTypeID,
   351  				typesByName,
   352  				bo,
   353  			},
   354  			sync.RWMutex{},
   355  			make(map[Type]Type),
   356  			make(map[Type]TypeID),
   357  		},
   358  		rawStrings,
   359  	}, nil
   360  }
   361  
   362  func indexTypes(types []Type, firstTypeID TypeID) (map[Type]TypeID, map[essentialName][]TypeID) {
   363  	namedTypes := 0
   364  	for _, typ := range types {
   365  		if typ.TypeName() != "" {
   366  			// Do a pre-pass to figure out how big types by name has to be.
   367  			// Most types have unique names, so it's OK to ignore essentialName
   368  			// here.
   369  			namedTypes++
   370  		}
   371  	}
   372  
   373  	typeIDs := make(map[Type]TypeID, len(types))
   374  	typesByName := make(map[essentialName][]TypeID, namedTypes)
   375  
   376  	for i, typ := range types {
   377  		id := firstTypeID + TypeID(i)
   378  		typeIDs[typ] = id
   379  
   380  		if name := newEssentialName(typ.TypeName()); name != "" {
   381  			typesByName[name] = append(typesByName[name], id)
   382  		}
   383  	}
   384  
   385  	return typeIDs, typesByName
   386  }
   387  
   388  func guessRawBTFByteOrder(r io.ReaderAt) binary.ByteOrder {
   389  	buf := new(bufio.Reader)
   390  	for _, bo := range []binary.ByteOrder{
   391  		binary.LittleEndian,
   392  		binary.BigEndian,
   393  	} {
   394  		buf.Reset(io.NewSectionReader(r, 0, math.MaxInt64))
   395  		if _, err := parseBTFHeader(buf, bo); err == nil {
   396  			return bo
   397  		}
   398  	}
   399  
   400  	return nil
   401  }
   402  
   403  // parseBTF reads a .BTF section into memory and parses it into a list of
   404  // raw types and a string table.
   405  func parseBTF(btf io.ReaderAt, bo binary.ByteOrder, baseStrings *stringTable, base *Spec) ([]Type, *stringTable, error) {
   406  	buf := internal.NewBufferedSectionReader(btf, 0, math.MaxInt64)
   407  	header, err := parseBTFHeader(buf, bo)
   408  	if err != nil {
   409  		return nil, nil, fmt.Errorf("parsing .BTF header: %v", err)
   410  	}
   411  
   412  	rawStrings, err := readStringTable(io.NewSectionReader(btf, header.stringStart(), int64(header.StringLen)),
   413  		baseStrings)
   414  	if err != nil {
   415  		return nil, nil, fmt.Errorf("can't read type names: %w", err)
   416  	}
   417  
   418  	buf.Reset(io.NewSectionReader(btf, header.typeStart(), int64(header.TypeLen)))
   419  	types, err := readAndInflateTypes(buf, bo, header.TypeLen, rawStrings, base)
   420  	if err != nil {
   421  		return nil, nil, err
   422  	}
   423  
   424  	return types, rawStrings, nil
   425  }
   426  
   427  type symbol struct {
   428  	section string
   429  	name    string
   430  }
   431  
   432  // fixupDatasec attempts to patch up missing info in Datasecs and its members by
   433  // supplementing them with information from the ELF headers and symbol table.
   434  func fixupDatasec(types []Type, sectionSizes map[string]uint32, offsets map[symbol]uint32) error {
   435  	for _, typ := range types {
   436  		ds, ok := typ.(*Datasec)
   437  		if !ok {
   438  			continue
   439  		}
   440  
   441  		name := ds.Name
   442  
   443  		// Some Datasecs are virtual and don't have corresponding ELF sections.
   444  		switch name {
   445  		case ".ksyms":
   446  			// .ksyms describes forward declarations of kfunc signatures.
   447  			// Nothing to fix up, all sizes and offsets are 0.
   448  			for _, vsi := range ds.Vars {
   449  				_, ok := vsi.Type.(*Func)
   450  				if !ok {
   451  					// Only Funcs are supported in the .ksyms Datasec.
   452  					return fmt.Errorf("data section %s: expected *btf.Func, not %T: %w", name, vsi.Type, ErrNotSupported)
   453  				}
   454  			}
   455  
   456  			continue
   457  		case ".kconfig":
   458  			// .kconfig has a size of 0 and has all members' offsets set to 0.
   459  			// Fix up all offsets and set the Datasec's size.
   460  			if err := fixupDatasecLayout(ds); err != nil {
   461  				return err
   462  			}
   463  
   464  			// Fix up extern to global linkage to avoid a BTF verifier error.
   465  			for _, vsi := range ds.Vars {
   466  				vsi.Type.(*Var).Linkage = GlobalVar
   467  			}
   468  
   469  			continue
   470  		}
   471  
   472  		if ds.Size != 0 {
   473  			continue
   474  		}
   475  
   476  		ds.Size, ok = sectionSizes[name]
   477  		if !ok {
   478  			return fmt.Errorf("data section %s: missing size", name)
   479  		}
   480  
   481  		for i := range ds.Vars {
   482  			symName := ds.Vars[i].Type.TypeName()
   483  			ds.Vars[i].Offset, ok = offsets[symbol{name, symName}]
   484  			if !ok {
   485  				return fmt.Errorf("data section %s: missing offset for symbol %s", name, symName)
   486  			}
   487  		}
   488  	}
   489  
   490  	return nil
   491  }
   492  
   493  // fixupDatasecLayout populates ds.Vars[].Offset according to var sizes and
   494  // alignment. Calculate and set ds.Size.
   495  func fixupDatasecLayout(ds *Datasec) error {
   496  	var off uint32
   497  
   498  	for i, vsi := range ds.Vars {
   499  		v, ok := vsi.Type.(*Var)
   500  		if !ok {
   501  			return fmt.Errorf("member %d: unsupported type %T", i, vsi.Type)
   502  		}
   503  
   504  		size, err := Sizeof(v.Type)
   505  		if err != nil {
   506  			return fmt.Errorf("variable %s: getting size: %w", v.Name, err)
   507  		}
   508  		align, err := alignof(v.Type)
   509  		if err != nil {
   510  			return fmt.Errorf("variable %s: getting alignment: %w", v.Name, err)
   511  		}
   512  
   513  		// Align the current member based on the offset of the end of the previous
   514  		// member and the alignment of the current member.
   515  		off = internal.Align(off, uint32(align))
   516  
   517  		ds.Vars[i].Offset = off
   518  
   519  		off += uint32(size)
   520  	}
   521  
   522  	ds.Size = off
   523  
   524  	return nil
   525  }
   526  
   527  // Copy creates a copy of Spec.
   528  func (s *Spec) Copy() *Spec {
   529  	if s == nil {
   530  		return nil
   531  	}
   532  
   533  	return &Spec{
   534  		s.mutableTypes.copy(),
   535  		s.strings,
   536  	}
   537  }
   538  
   539  type sliceWriter []byte
   540  
   541  func (sw sliceWriter) Write(p []byte) (int, error) {
   542  	if len(p) != len(sw) {
   543  		return 0, errors.New("size doesn't match")
   544  	}
   545  
   546  	return copy(sw, p), nil
   547  }
   548  
   549  // nextTypeID returns the next unallocated type ID or an error if there are no
   550  // more type IDs.
   551  func (s *Spec) nextTypeID() (TypeID, error) {
   552  	id := s.imm.firstTypeID + TypeID(len(s.imm.types))
   553  	if id < s.imm.firstTypeID {
   554  		return 0, fmt.Errorf("no more type IDs")
   555  	}
   556  	return id, nil
   557  }
   558  
   559  // TypeByID returns the BTF Type with the given type ID.
   560  //
   561  // Returns an error wrapping ErrNotFound if a Type with the given ID
   562  // does not exist in the Spec.
   563  func (s *Spec) TypeByID(id TypeID) (Type, error) {
   564  	typ, ok := s.typeByID(id)
   565  	if !ok {
   566  		return nil, fmt.Errorf("look up type with ID %d (first ID is %d): %w", id, s.imm.firstTypeID, ErrNotFound)
   567  	}
   568  
   569  	return typ, nil
   570  }
   571  
   572  // TypeID returns the ID for a given Type.
   573  //
   574  // Returns an error wrapping [ErrNotFound] if the type isn't part of the Spec.
   575  func (s *Spec) TypeID(typ Type) (TypeID, error) {
   576  	return s.mutableTypes.typeID(typ)
   577  }
   578  
   579  // AnyTypesByName returns a list of BTF Types with the given name.
   580  //
   581  // If the BTF blob describes multiple compilation units like vmlinux, multiple
   582  // Types with the same name and kind can exist, but might not describe the same
   583  // data structure.
   584  //
   585  // Returns an error wrapping ErrNotFound if no matching Type exists in the Spec.
   586  func (s *Spec) AnyTypesByName(name string) ([]Type, error) {
   587  	return s.mutableTypes.anyTypesByName(name)
   588  }
   589  
   590  // AnyTypeByName returns a Type with the given name.
   591  //
   592  // Returns an error if multiple types of that name exist.
   593  func (s *Spec) AnyTypeByName(name string) (Type, error) {
   594  	types, err := s.AnyTypesByName(name)
   595  	if err != nil {
   596  		return nil, err
   597  	}
   598  
   599  	if len(types) > 1 {
   600  		return nil, fmt.Errorf("found multiple types: %v", types)
   601  	}
   602  
   603  	return types[0], nil
   604  }
   605  
   606  // TypeByName searches for a Type with a specific name. Since multiple Types
   607  // with the same name can exist, the parameter typ is taken to narrow down the
   608  // search in case of a clash.
   609  //
   610  // typ must be a non-nil pointer to an implementation of a Type. On success, the
   611  // address of the found Type will be copied to typ.
   612  //
   613  // Returns an error wrapping ErrNotFound if no matching Type exists in the Spec.
   614  // Returns an error wrapping ErrMultipleTypes if multiple candidates are found.
   615  func (s *Spec) TypeByName(name string, typ interface{}) error {
   616  	typeInterface := reflect.TypeOf((*Type)(nil)).Elem()
   617  
   618  	// typ may be **T or *Type
   619  	typValue := reflect.ValueOf(typ)
   620  	if typValue.Kind() != reflect.Ptr {
   621  		return fmt.Errorf("%T is not a pointer", typ)
   622  	}
   623  
   624  	typPtr := typValue.Elem()
   625  	if !typPtr.CanSet() {
   626  		return fmt.Errorf("%T cannot be set", typ)
   627  	}
   628  
   629  	wanted := typPtr.Type()
   630  	if wanted == typeInterface {
   631  		// This is *Type. Unwrap the value's type.
   632  		wanted = typPtr.Elem().Type()
   633  	}
   634  
   635  	if !wanted.AssignableTo(typeInterface) {
   636  		return fmt.Errorf("%T does not satisfy Type interface", typ)
   637  	}
   638  
   639  	types, err := s.AnyTypesByName(name)
   640  	if err != nil {
   641  		return err
   642  	}
   643  
   644  	var candidate Type
   645  	for _, typ := range types {
   646  		if reflect.TypeOf(typ) != wanted {
   647  			continue
   648  		}
   649  
   650  		if candidate != nil {
   651  			return fmt.Errorf("type %s(%T): %w", name, typ, ErrMultipleMatches)
   652  		}
   653  
   654  		candidate = typ
   655  	}
   656  
   657  	if candidate == nil {
   658  		return fmt.Errorf("%s %s: %w", wanted, name, ErrNotFound)
   659  	}
   660  
   661  	typPtr.Set(reflect.ValueOf(candidate))
   662  
   663  	return nil
   664  }
   665  
   666  // LoadSplitSpecFromReader loads split BTF from a reader.
   667  //
   668  // Types from base are used to resolve references in the split BTF.
   669  // The returned Spec only contains types from the split BTF, not from the base.
   670  func LoadSplitSpecFromReader(r io.ReaderAt, base *Spec) (*Spec, error) {
   671  	return loadRawSpec(r, internal.NativeEndian, base)
   672  }
   673  
   674  // TypesIterator iterates over types of a given spec.
   675  type TypesIterator struct {
   676  	spec *Spec
   677  	id   TypeID
   678  	done bool
   679  	// The last visited type in the spec.
   680  	Type Type
   681  }
   682  
   683  // Iterate returns the types iterator.
   684  func (s *Spec) Iterate() *TypesIterator {
   685  	return &TypesIterator{spec: s, id: s.imm.firstTypeID}
   686  }
   687  
   688  // Next returns true as long as there are any remaining types.
   689  func (iter *TypesIterator) Next() bool {
   690  	if iter.done {
   691  		return false
   692  	}
   693  
   694  	var ok bool
   695  	iter.Type, ok = iter.spec.typeByID(iter.id)
   696  	iter.id++
   697  	iter.done = !ok
   698  	return !iter.done
   699  }