Skip to content

Commit

Permalink
tools: bpftool: resolve calls without using imm field
Browse files Browse the repository at this point in the history
Currently, we resolve the callee's address for a JITed function
call by using the imm field of the call instruction as an offset
from __bpf_call_base. If bpf_jit_kallsyms is enabled, we further
use this address to get the callee's kernel symbol's name.

For some architectures, such as powerpc64, the imm field is not
large enough to hold this offset. So, instead of assigning this
offset to the imm field, the verifier now assigns the subprog
id. Also, a list of kernel symbol addresses for all the JITed
functions is provided in the program info. We now use the imm
field as an index for this list to lookup a callee's symbol's
address and resolve its name.

Suggested-by: Daniel Borkmann <daniel@iogearbox.net>
Signed-off-by: Sandipan Das <sandipan@linux.vnet.ibm.com>
Reviewed-by: Jakub Kicinski <jakub.kicinski@netronome.com>
Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
  • Loading branch information
Sandipan Das authored and Daniel Borkmann committed May 24, 2018
1 parent dd0c5f0 commit f84192e
Show file tree
Hide file tree
Showing 3 changed files with 35 additions and 1 deletion.
24 changes: 24 additions & 0 deletions tools/bpf/bpftool/prog.c
Original file line number Diff line number Diff line change
Expand Up @@ -420,7 +420,9 @@ static int do_show(int argc, char **argv)

static int do_dump(int argc, char **argv)
{
unsigned long *func_ksyms = NULL;
struct bpf_prog_info info = {};
unsigned int nr_func_ksyms;
struct dump_data dd = {};
__u32 len = sizeof(info);
unsigned int buf_size;
Expand Down Expand Up @@ -496,10 +498,22 @@ static int do_dump(int argc, char **argv)
return -1;
}

nr_func_ksyms = info.nr_jited_ksyms;
if (nr_func_ksyms) {
func_ksyms = malloc(nr_func_ksyms * sizeof(__u64));
if (!func_ksyms) {
p_err("mem alloc failed");
close(fd);
goto err_free;
}
}

memset(&info, 0, sizeof(info));

*member_ptr = ptr_to_u64(buf);
*member_len = buf_size;
info.jited_ksyms = ptr_to_u64(func_ksyms);
info.nr_jited_ksyms = nr_func_ksyms;

err = bpf_obj_get_info_by_fd(fd, &info, &len);
close(fd);
Expand All @@ -513,6 +527,11 @@ static int do_dump(int argc, char **argv)
goto err_free;
}

if (info.nr_jited_ksyms > nr_func_ksyms) {
p_err("too many addresses returned");
goto err_free;
}

if ((member_len == &info.jited_prog_len &&
info.jited_prog_insns == 0) ||
(member_len == &info.xlated_prog_len &&
Expand Down Expand Up @@ -558,6 +577,9 @@ static int do_dump(int argc, char **argv)
dump_xlated_cfg(buf, *member_len);
} else {
kernel_syms_load(&dd);
dd.nr_jited_ksyms = info.nr_jited_ksyms;
dd.jited_ksyms = (__u64 *) info.jited_ksyms;

if (json_output)
dump_xlated_json(&dd, buf, *member_len, opcodes);
else
Expand All @@ -566,10 +588,12 @@ static int do_dump(int argc, char **argv)
}

free(buf);
free(func_ksyms);
return 0;

err_free:
free(buf);
free(func_ksyms);
return -1;
}

Expand Down
10 changes: 9 additions & 1 deletion tools/bpf/bpftool/xlated_dumper.c
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,11 @@ static const char *print_call_pcrel(struct dump_data *dd,
unsigned long address,
const struct bpf_insn *insn)
{
if (sym)
if (!dd->nr_jited_ksyms)
/* Do not show address for interpreted programs */
snprintf(dd->scratch_buff, sizeof(dd->scratch_buff),
"%+d", insn->off);
else if (sym)
snprintf(dd->scratch_buff, sizeof(dd->scratch_buff),
"%+d#%s", insn->off, sym->name);
else
Expand Down Expand Up @@ -203,6 +207,10 @@ static const char *print_call(void *private_data,
unsigned long address = dd->address_call_base + insn->imm;
struct kernel_sym *sym;

if (insn->src_reg == BPF_PSEUDO_CALL &&
(__u32) insn->imm < dd->nr_jited_ksyms)
address = dd->jited_ksyms[insn->imm];

sym = kernel_syms_search(dd, address);
if (insn->src_reg == BPF_PSEUDO_CALL)
return print_call_pcrel(dd, sym, address, insn);
Expand Down
2 changes: 2 additions & 0 deletions tools/bpf/bpftool/xlated_dumper.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@ struct dump_data {
unsigned long address_call_base;
struct kernel_sym *sym_mapping;
__u32 sym_count;
__u64 *jited_ksyms;
__u32 nr_jited_ksyms;
char scratch_buff[SYM_MAX_NAME + 8];
};

Expand Down

0 comments on commit f84192e

Please sign in to comment.