code: func ReadSymbols(bs ByteSlice, version int, off int) ([]string, map[uint32]string, error) {
  	if off == 0 {
  		return nil, nil, nil
  	}
  	d := encoding.NewDecbufAt(bs, off, castagnoliTable)
  
  	var (
  		origLen     = d.Len()
  		cnt         = d.Be32int()
  		basePos     = uint32(off) + 4
  		nextPos     = basePos + uint32(origLen-d.Len())
  		symbolSlice []string
  		symbols     = map[uint32]string{}
  	)
  	if version == FormatV2 {
  		symbolSlice = make([]string, 0, cnt)
  	}
  
  	for d.Err() == nil && d.Len() > 0 && cnt > 0 {
  		s := d.UvarintStr()
  
  		if version == FormatV2 {
  			symbolSlice = append(symbolSlice, s)
  		} else {
  			symbols[nextPos] = s
  			nextPos = basePos + uint32(origLen-d.Len())
  		}
  		cnt--
  	}
  	return symbolSlice, symbols, errors.Wrap(d.Err(), "read symbols")
  }
docs: // ReadSymbols reads the symbol table fully into memory and allocates proper strings for them.
  // Strings backed by the mmap'd memory would cause memory faults if applications keep using them
  // after the reader is closed.