@@ -1084,6 +1085,7 @@ static int do_help(int argc, char **argv)
fprintf(stderr,
"Usage: %1$s %2$s object OUTPUT_FILE INPUT_FILE [INPUT_FILE...]\n"
" %1$s %2$s skeleton FILE [name OBJECT_NAME]\n"
+ " %1$s %2$s btf INPUT OUTPUT OBJECT(S)\n"
" %1$s %2$s help\n"
"\n"
" " HELP_SPEC_OPTIONS " |\n"
@@ -1094,9 +1096,124 @@ static int do_help(int argc, char **argv)
return 0;
}
+/* Create BTF file for a set of BPF objects */
+static int btfgen(const char *src_btf, const char *dst_btf, const char *objspaths[])
+{
+ return -EOPNOTSUPP;
+}
+
+static int is_file(const char *path)
+{
+ struct stat st;
+
+ if (stat(path, &st) < 0)
+ return -1;
+
+ switch (st.st_mode & S_IFMT) {
+ case S_IFDIR:
+ return 0;
+ case S_IFREG:
+ return 1;
+ default:
+ return -1;
+ }
+}
+
+static int do_gen_btf(int argc, char **argv)
+{
+ char src_btf_path[PATH_MAX], dst_btf_path[PATH_MAX];
+ bool input_is_file, output_is_file = false;
+ const char *input, *output;
+ const char **objs = NULL;
+ struct dirent *dir;
+ DIR *d = NULL;
+ int i, err;
+
+ if (!REQ_ARGS(3)) {
+ usage();
+ return -1;
+ }
+
+ input = GET_ARG();
+ err = is_file(input);
+ if (err < 0) {
+ p_err("failed to stat %s: %s", input, strerror(errno));
+ return err;
+ }
+ input_is_file = err;
+
+ output = GET_ARG();
+ err = is_file(output);
+ if (err != 0)
+ output_is_file = true;
+
+ objs = (const char **) malloc((argc + 1) * sizeof(*objs));
+ if (!objs)
+ return -ENOMEM;
+
+ i = 0;
+ while (argc > 0)
+ objs[i++] = GET_ARG();
+
+ objs[i] = NULL;
+
+ /* single BTF file */
+ if (input_is_file) {
+ printf("SBTF: %s\n", input);
+
+ if (output_is_file) {
+ err = btfgen(input, output, objs);
+ goto out;
+ }
+ snprintf(dst_btf_path, sizeof(dst_btf_path), "%s/%s", output,
+ basename(input));
+ err = btfgen(input, dst_btf_path, objs);
+ goto out;
+ }
+
+ if (output_is_file) {
+ p_err("can't have just one file as output");
+ err = -EINVAL;
+ goto out;
+ }
+
+ /* directory with BTF files */
+ d = opendir(input);
+ if (!d) {
+ p_err("error opening input dir: %s", strerror(errno));
+ err = -errno;
+ goto out;
+ }
+
+ while ((dir = readdir(d)) != NULL) {
+ if (dir->d_type != DT_REG)
+ continue;
+
+ if (strncmp(dir->d_name + strlen(dir->d_name) - 4, ".btf", 4))
+ continue;
+
+ snprintf(src_btf_path, sizeof(src_btf_path), "%s/%s", input, dir->d_name);
+ snprintf(dst_btf_path, sizeof(dst_btf_path), "%s/%s", output, dir->d_name);
+
+ printf("SBTF: %s\n", src_btf_path);
+
+ err = btfgen(src_btf_path, dst_btf_path, objs);
+ if (err)
+ goto out;
+ }
+
+out:
+ if (!err)
+ printf("STAT: done!\n");
+ free(objs);
+ closedir(d);
+ return err;
+}
+
static const struct cmd cmds[] = {
{ "object", do_object },
{ "skeleton", do_skeleton },
+ { "btf", do_gen_btf},
{ "help", do_help },
{ 0 }
};