bool abs;
};
-struct var_preset {
- char *name;
+struct rvalue {
enum { INTEGRAL, ENUMERATOR } type;
union {
long long ivalue;
char *svalue;
};
+};
+
+struct field_access {
+ char *name;
+};
+
+struct var_preset {
+ struct field_access *atoms;
+ int atom_count;
+ char *full_name;
+ struct rvalue value;
bool applied;
};
return 0;
}
+static int parse_rvalue(const char *val, struct rvalue *rvalue)
+{
+ long long value;
+ char *val_end;
+
+ if (val[0] == '-' || isdigit(val[0])) {
+ /* must be a number */
+ errno = 0;
+ value = strtoll(val, &val_end, 0);
+ if (errno == ERANGE) {
+ errno = 0;
+ value = strtoull(val, &val_end, 0);
+ }
+ if (errno || *val_end != '\0') {
+ fprintf(stderr, "Failed to parse value '%s'\n", val);
+ return -EINVAL;
+ }
+ rvalue->ivalue = value;
+ rvalue->type = INTEGRAL;
+ } else {
+ /* if not a number, consider it enum value */
+ rvalue->svalue = strdup(val);
+ if (!rvalue->svalue)
+ return -ENOMEM;
+ rvalue->type = ENUMERATOR;
+ }
+ return 0;
+}
+
static int process_prog(const char *filename, struct bpf_object *obj, struct bpf_program *prog)
{
const char *base_filename = basename(strdupa(filename));
return 0;
};
+static int parse_var_atoms(const char *full_var, struct var_preset *preset)
+{
+ char expr[256], *name, *saveptr;
+
+ snprintf(expr, sizeof(expr), "%s", full_var);
+ preset->atom_count = 0;
+ while ((name = strtok_r(preset->atom_count ? NULL : expr, ".", &saveptr))) {
+ struct field_access *tmp;
+ int i = preset->atom_count;
+
+ tmp = reallocarray(preset->atoms, i + 1, sizeof(*preset->atoms));
+ if (!tmp)
+ return -ENOMEM;
+
+ preset->atoms = tmp;
+ preset->atom_count++;
+
+ preset->atoms[i].name = strdup(name);
+ if (!preset->atoms[i].name)
+ return -ENOMEM;
+ }
+ return 0;
+}
+
static int append_var_preset(struct var_preset **presets, int *cnt, const char *expr)
{
void *tmp;
struct var_preset *cur;
- char var[256], val[256], *val_end;
- long long value;
- int n;
+ char var[256], val[256];
+ int n, err;
tmp = realloc(*presets, (*cnt + 1) * sizeof(**presets));
if (!tmp)
return -EINVAL;
}
- if (val[0] == '-' || isdigit(val[0])) {
- /* must be a number */
- errno = 0;
- value = strtoll(val, &val_end, 0);
- if (errno == ERANGE) {
- errno = 0;
- value = strtoull(val, &val_end, 0);
- }
- if (errno || *val_end != '\0') {
- fprintf(stderr, "Failed to parse value '%s'\n", val);
- return -EINVAL;
- }
- cur->ivalue = value;
- cur->type = INTEGRAL;
- } else {
- /* if not a number, consider it enum value */
- cur->svalue = strdup(val);
- if (!cur->svalue)
- return -ENOMEM;
- cur->type = ENUMERATOR;
- }
+ err = parse_rvalue(val, &cur->value);
+ if (err)
+ return err;
- cur->name = strdup(var);
- if (!cur->name)
+ cur->full_name = strdup(var);
+ if (!cur->full_name)
return -ENOMEM;
+ err = parse_var_atoms(var, cur);
+ if (err)
+ return err;
+
return 0;
}
}
static int adjust_var_secinfo(struct btf *btf, const struct btf_type *t,
- struct btf_var_secinfo *sinfo, const char *var)
+ struct btf_var_secinfo *sinfo, struct var_preset *preset)
{
- char expr[256], *saveptr;
const struct btf_type *base_type, *member_type;
- int err, member_tid;
- char *name;
+ int err, member_tid, i;
__u32 member_offset = 0;
base_type = btf__type_by_id(btf, btf__resolve_type(btf, t->type));
- snprintf(expr, sizeof(expr), "%s", var);
- strtok_r(expr, ".", &saveptr);
- while ((name = strtok_r(NULL, ".", &saveptr))) {
- err = btf_find_member(btf, base_type, 0, name, &member_tid, &member_offset);
+ for (i = 1; i < preset->atom_count; ++i) {
+ err = btf_find_member(btf, base_type, 0, preset->atoms[i].name,
+ &member_tid, &member_offset);
if (err) {
- fprintf(stderr, "Could not find member %s for variable %s\n", name, var);
+ fprintf(stderr, "Could not find member %s for variable %s\n",
+ preset->atoms[i].name, preset->atoms[i - 1].name);
return err;
}
member_type = btf__type_by_id(btf, member_tid);
{
const struct btf_type *base_type;
void *ptr;
- long long value = preset->ivalue;
+ long long value = preset->value.ivalue;
size_t size;
base_type = btf__type_by_id(btf, btf__resolve_type(btf, sinfo->type));
return -EINVAL;
}
- if (preset->type == ENUMERATOR) {
+ if (preset->value.type == ENUMERATOR) {
if (btf_is_any_enum(base_type)) {
- if (enum_value_from_name(btf, base_type, preset->svalue, &value)) {
+ if (enum_value_from_name(btf, base_type, preset->value.svalue, &value)) {
fprintf(stderr,
"Failed to find integer value for enum element %s\n",
- preset->svalue);
+ preset->value.svalue);
return -EINVAL;
}
} else {
fprintf(stderr, "Value %s is not supported for type %s\n",
- preset->svalue, btf__name_by_offset(btf, base_type->name_off));
+ preset->value.svalue,
+ btf__name_by_offset(btf, base_type->name_off));
return -EINVAL;
}
}
for (j = 0; j < n; ++j, ++sinfo) {
const struct btf_type *var_type = btf__type_by_id(btf, sinfo->type);
const char *var_name;
- int var_len;
if (!btf_is_var(var_type))
continue;
var_name = btf__name_by_offset(btf, var_type->name_off);
- var_len = strlen(var_name);
for (k = 0; k < npresets; ++k) {
struct btf_var_secinfo tmp_sinfo;
- if (strncmp(var_name, presets[k].name, var_len) != 0 ||
- (presets[k].name[var_len] != '\0' &&
- presets[k].name[var_len] != '.'))
+ if (strcmp(var_name, presets[k].atoms[0].name) != 0)
continue;
if (presets[k].applied) {
}
tmp_sinfo = *sinfo;
err = adjust_var_secinfo(btf, var_type,
- &tmp_sinfo, presets[k].name);
+ &tmp_sinfo, presets + k);
if (err)
return err;
for (i = 0; i < npresets; ++i) {
if (!presets[i].applied) {
fprintf(stderr, "Global variable preset %s has not been applied\n",
- presets[i].name);
+ presets[i].full_name);
}
presets[i].applied = false;
}
int main(int argc, char **argv)
{
- int err = 0, i;
+ int err = 0, i, j;
if (argp_parse(&argp, argc, argv, 0, NULL, NULL))
return 1;
}
free(env.deny_filters);
for (i = 0; i < env.npresets; ++i) {
- free(env.presets[i].name);
- if (env.presets[i].type == ENUMERATOR)
- free(env.presets[i].svalue);
+ free(env.presets[i].full_name);
+ for (j = 0; j < env.presets[i].atom_count; ++j)
+ free(env.presets[i].atoms[j].name);
+ free(env.presets[i].atoms);
+ if (env.presets[i].value.type == ENUMERATOR)
+ free(env.presets[i].value.svalue);
}
free(env.presets);
return -err;