code: func (d *llvmSymbolizer) readFrame() (plugin.Frame, bool) {
  	funcname, err := d.readString()
  	if err != nil {
  		return plugin.Frame{}, true
  	}
  
  	switch funcname {
  	case "":
  		return plugin.Frame{}, true
  	case "??":
  		funcname = ""
  	}
  
  	fileline, err := d.readString()
  	if err != nil {
  		return plugin.Frame{Func: funcname}, true
  	}
  
  	linenumber := 0
  	if fileline == "??:0" {
  		fileline = ""
  	} else {
  		switch split := strings.Split(fileline, ":"); len(split) {
  		case 1:
  			// filename
  			fileline = split[0]
  		case 2, 3:
  			// filename:line , or
  			// filename:line:disc , or
  			fileline = split[0]
  			if line, err := strconv.Atoi(split[1]); err == nil {
  				linenumber = line
  			}
  		default:
  			// Unrecognized, ignore
  		}
  	}
  
  	return plugin.Frame{Func: funcname, File: fileline, Line: linenumber}, false
  }
docs: // readFrame parses the llvm-symbolizer output for a single address. It
  // returns a populated plugin.Frame and whether it has reached the end of the
  // data.