}
if (i != bpf_len) {
- fprintf(stderr, "Parsed program length is less than encodedlength parameter!\n");
+ fprintf(stderr, "Parsed program length is less than encoded length parameter!\n");
ret = -EINVAL;
goto out;
}
ops[i].jf, ops[i].k);
}
+static void bpf_map_pin_report(const struct bpf_elf_map *pin,
+ const struct bpf_elf_map *obj)
+{
+ fprintf(stderr, "Map specification differs from pinned file!\n");
+
+ if (obj->type != pin->type)
+ fprintf(stderr, " - Type: %u (obj) != %u (pin)\n",
+ obj->type, pin->type);
+ if (obj->size_key != pin->size_key)
+ fprintf(stderr, " - Size key: %u (obj) != %u (pin)\n",
+ obj->size_key, pin->size_key);
+ if (obj->size_value != pin->size_value)
+ fprintf(stderr, " - Size value: %u (obj) != %u (pin)\n",
+ obj->size_value, pin->size_value);
+ if (obj->max_elem != pin->max_elem)
+ fprintf(stderr, " - Max elems: %u (obj) != %u (pin)\n",
+ obj->max_elem, pin->max_elem);
+
+ fprintf(stderr, "\n");
+}
+
static int bpf_map_selfcheck_pinned(int fd, const struct bpf_elf_map *map,
int length)
{
if (!memcmp(&tmp, &zero, length))
return 0;
- fprintf(stderr, "Map specs from pinned file differ!\n");
+ bpf_map_pin_report(&tmp, map);
return -EINVAL;
}
}
va_end(vl);
if (ctx->log && ctx->log[0]) {
- fprintf(stderr, "%s\n", ctx->log);
+ if (ctx->verbose) {
+ fprintf(stderr, "%s\n", ctx->log);
+ } else {
+ unsigned int off = 0, len = strlen(ctx->log);
+
+ if (len > BPF_MAX_LOG) {
+ off = len - BPF_MAX_LOG;
+ fprintf(stderr, "Skipped %u bytes, use \'verb\' option for the full verbose log.\n[...]\n",
+ off);
+ }
+ fprintf(stderr, "%s\n", ctx->log + off);
+ }
+
memset(ctx->log, 0, ctx->log_size);
}
}
const struct bpf_elf_prog *prog,
struct bpf_elf_ctx *ctx)
{
- fprintf(stderr, "Prog section \'%s\' %s%s (%d)!\n", section,
+ unsigned int insns = prog->size / sizeof(struct bpf_insn);
+
+ fprintf(stderr, "\nProg section \'%s\' %s%s (%d)!\n", section,
fd < 0 ? "rejected: " : "loaded",
fd < 0 ? strerror(errno) : "",
fd < 0 ? errno : fd);
fprintf(stderr, " - Type: %u\n", prog->type);
- fprintf(stderr, " - Instructions: %zu\n",
- prog->size / sizeof(struct bpf_insn));
+ fprintf(stderr, " - Instructions: %u (%u over limit)\n",
+ insns, insns > BPF_MAXINSNS ? insns - BPF_MAXINSNS : 0);
fprintf(stderr, " - License: %s\n\n", prog->license);
bpf_dump_error(ctx, "Verifier analysis:\n\n");
return 0;
}
+static bool bpf_has_map_data(const struct bpf_elf_ctx *ctx)
+{
+ return ctx->sym_tab && ctx->str_tab && ctx->sec_maps;
+}
+
static int bpf_fetch_ancillary(struct bpf_elf_ctx *ctx)
{
struct bpf_elf_sec_data data;
!strcmp(data.sec_name, ".strtab"))
ret = bpf_fetch_strtab(ctx, i, &data);
if (ret < 0) {
- fprintf(stderr, "Error parsing section %d! Perhapscheck with readelf -a?\n",
+ fprintf(stderr, "Error parsing section %d! Perhaps check with readelf -a?\n",
i);
break;
}
}
- if (ctx->sym_tab && ctx->str_tab && ctx->sec_maps) {
+ if (bpf_has_map_data(ctx)) {
ret = bpf_maps_attach_all(ctx);
if (ret < 0) {
fprintf(stderr, "Error loading maps into kernel!\n");
fd = bpf_prog_attach(section, &prog, ctx);
if (fd < 0)
- continue;
+ break;
ctx->sec_done[i] = true;
break;
return 0;
}
-static int bpf_fetch_prog_relo(struct bpf_elf_ctx *ctx, const char *section)
+static int bpf_fetch_prog_relo(struct bpf_elf_ctx *ctx, const char *section,
+ bool *lderr)
{
struct bpf_elf_sec_data data_relo, data_insn;
struct bpf_elf_prog prog;
prog.license = ctx->license;
fd = bpf_prog_attach(section, &prog, ctx);
- if (fd < 0)
- continue;
+ if (fd < 0) {
+ *lderr = true;
+ break;
+ }
ctx->sec_done[i] = true;
ctx->sec_done[idx] = true;
static int bpf_fetch_prog_sec(struct bpf_elf_ctx *ctx, const char *section)
{
+ bool lderr = false;
int ret = -1;
- if (ctx->sym_tab)
- ret = bpf_fetch_prog_relo(ctx, section);
- if (ret < 0)
+ if (bpf_has_map_data(ctx))
+ ret = bpf_fetch_prog_relo(ctx, section, &lderr);
+ if (ret < 0 && !lderr)
ret = bpf_fetch_prog(ctx, section);
return ret;
ret = bpf_map_update(ctx->map_fds[idx], &key_id,
&fd, BPF_ANY);
- if (ret < 0)
- return -ENOENT;
+ if (ret < 0) {
+ if (errno == E2BIG)
+ fprintf(stderr, "Tail call key %u for map %u out of bounds?\n",
+ key_id, map_id);
+ return -errno;
+ }
ctx->sec_done[i] = true;
}