func()

in auditbeat/tracing/tracefs.go [252:362]


func (dfs *TraceFS) LoadProbeFormat(probe Probe) (format ProbeFormat, err error) {
	path := filepath.Join(dfs.basePath, "events", probe.EffectiveGroup(), probe.Name, "format")
	file, err := os.Open(path)
	if err != nil {
		return format, err
	}
	defer file.Close()
	format.Probe = probe
	format.Fields = make(map[string]Field)
	scanner := bufio.NewScanner(file)
	parseFormat := false
	for scanner.Scan() {
		line := scanner.Text()
		if !parseFormat {
			// Parse the header
			parts := strings.SplitN(line, ": ", 2)
			switch {
			case len(parts) == 2 && parts[0] == "ID":
				if format.ID, err = strconv.Atoi(parts[1]); err != nil {
					return format, err
				}
			case len(parts) == 1 && parts[0] == "format:":
				parseFormat = true
			}
		} else {
			// Parse the fields
			// Ends on the first line that doesn't start with a TAB
			if len(line) > 0 && line[0] != '\t' && line[0] != ' ' {
				break
			}

			// Find all "<key>:<value>;" matches
			// The actual format is:
			// "\tfield:%s %s;\toffset:%u;\tsize:%u;\tsigned:%d;\n"
			var f Field
			matches := formatRegexp.FindAllStringSubmatch(line, -1)
			if len(matches) != 4 {
				continue
			}

			for _, match := range matches {
				if len(match) != 3 {
					continue
				}
				key, value := match[1], match[2]
				switch key {
				case "field":
					fparts := strings.Split(value, " ")
					n := len(fparts)
					if n < 2 {
						return format, fmt.Errorf("bad format for kprobe '%s': `field` has no type: %s", probe.String(), value)
					}

					fparts, f.Name = fparts[:n-1], fparts[n-1]
					typeIdx, isDataLoc := -1, false

					for idx, part := range fparts {
						switch part {
						case "signed", "unsigned":
							// ignore
						case "__data_loc":
							isDataLoc = true
						default:
							if typeIdx != -1 {
								return format, fmt.Errorf("bad format for kprobe '%s': unknown parameter=`%s` in type=`%s`", probe.String(), part, value)
							}
							typeIdx = idx
						}
					}
					if typeIdx == -1 {
						return format, fmt.Errorf("bad format for kprobe '%s': type not found in `%s`", probe.String(), value)
					}
					intLen, isInt := integerTypes[fparts[typeIdx]]
					if isInt {
						f.Type = FieldTypeInteger
						f.Size = int(intLen)
					} else {
						if fparts[typeIdx] != "char[]" || !isDataLoc {
							return format, fmt.Errorf("bad format for kprobe '%s': unsupported type in `%s`", probe.String(), value)
						}
						f.Type = FieldTypeString
					}

				case "offset":
					f.Offset, err = strconv.Atoi(value)
					if err != nil {
						return format, err
					}

				case "size":
					prev := f.Size
					f.Size, err = strconv.Atoi(value)
					if err != nil {
						return format, err
					}
					if prev != 0 && prev != f.Size {
						return format, fmt.Errorf("bad format for kprobe '%s': int field length mismatch at `%s`", probe.String(), line)
					}

				case "signed":
					f.Signed = len(value) > 0 && value[0] == '1'
				}
			}
			if f.Type == FieldTypeString && f.Size != 4 {
				return format, fmt.Errorf("bad format for kprobe '%s': unexpected size for string in `%s`", probe.String(), line)
			}
			format.Fields[f.Name] = f
		}
	}
	return format, nil
}