bpf.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Andrii Nakryiko <andrii.nakryiko@gmail.com>
To: Yaniv Agman <yanivagman@gmail.com>
Cc: bpf <bpf@vger.kernel.org>
Subject: Re: Help using libbpf with kernel 4.14
Date: Mon, 28 Sep 2020 18:28:55 -0700	[thread overview]
Message-ID: <CAEf4BzZ=w++q3VVG8Mox4KsRHfY4P4J7G0Pnse2erWS6=OX3UQ@mail.gmail.com> (raw)
In-Reply-To: <CAMy7=ZUgWyZNVs6haL4MF2hZ24MuvfE_mEOXopgVZFGF_D8miA@mail.gmail.com>

On Mon, Sep 28, 2020 at 5:01 PM Yaniv Agman <yanivagman@gmail.com> wrote:
>
> Hi Andrii,
>
> I used BPF skeleton as you suggested, which did work with kernel 4.19
> but not with 4.14.
> I used the exact same program,  same environment, only changed the
> kernel version.
> The error message I get on 4.14:
>
> libbpf: elf: skipping unrecognized data section(5) .rodata.str1.1
> libbpf: failed to determine kprobe perf type: No such file or directory

This means that your kernel doesn't support attaching to
kprobe/tracepoint through perf_event subsystem. That's currently the
only way that libbpf supports for kprobe/tracapoint programs. It was
added in 4.17 kernel, which explains what is happening in your case.
It is still possible to attach to kprobe using legacy ways, but libbpf
doesn't provide that out of the box. We had a discussion a while ago
(about 1 year ago) about adding that to libbpf, but at that time we
didn't have a good testing infrastructure to validate such legacy
interfaces, plus it's a bit on the unsafe side as far as APIs go
(there is no auto-detachment and cleanup with how old kernels allow to
do kprobe/tracepoint). But we might reconsider, given it's not a first
time I see people get confused and blocked by this.

Anyways, here's how you can do it without waiting for libbpf to do
this out of the box:


int poke_kprobe_events(bool add, const char* name, bool ret) {
  char buf[256];
  int fd, err;

  fd = open("/sys/kernel/debug/tracing/kprobe_events", O_WRONLY | O_APPEND, 0);
  if (fd < 0) {
    err = -errno;
    fprintf(stderr, "failed to open kprobe_events file: %d\n", err);
    return err;
  }

  if (add)
    snprintf(buf, sizeof(buf), "%c:kprobes/%s %s", ret ? 'r' : 'p', name, name);
  else
    snprintf(buf, sizeof(buf), "-:kprobes/%s", name);

  err = write(fd, buf, strlen(buf));
  if (err < 0) {
    err = -errno;
    fprintf(
        stderr,
        "failed to %s kprobe '%s': %d\n",
        add ? "add" : "remove",
        buf,
        err);
  }
  close(fd);
  return err >= 0 ? 0 : err;
}

int add_kprobe_event(const char* func_name, bool is_kretprobe) {
  return poke_kprobe_events(true /*add*/, func_name, is_kretprobe);
}

int remove_kprobe_event(const char* func_name, bool is_kretprobe) {
  return poke_kprobe_events(false /*remove*/, func_name, is_kretprobe);
}

struct bpf_link* attach_kprobe_legacy(
    struct bpf_program* prog,
    const char* func_name,
    bool is_kretprobe) {
  char fname[256], buf[256];
  struct perf_event_attr attr;
  struct bpf_link* link;
  int fd = -1, err, id;
  FILE* f = NULL;

  err = add_kprobe_event(func_name, is_kretprobe);
  if (err) {
    fprintf(stderr, "failed to create kprobe event: %d\n", err);
    return NULL;
  }

  snprintf(
      fname,
      sizeof(fname),
      "/sys/kernel/debug/tracing/events/kprobes/%s/id",
      func_name);
  f = fopen(fname, "r");
  if (!f) {
    fprintf(stderr, "failed to open kprobe id file '%s': %d\n", fname, -errno);
    goto err_out;
  }

  if (fscanf(f, "%d\n", &id) != 1) {
    fprintf(stderr, "failed to read kprobe id from '%s': %d\n", fname, -errno);
    goto err_out;
  }

  fclose(f);
  f = NULL;

  memset(&attr, 0, sizeof(attr));
  attr.size = sizeof(attr);
  attr.config = id;
  attr.type = PERF_TYPE_TRACEPOINT;
  attr.sample_period = 1;
  attr.wakeup_events = 1;

  fd = syscall(__NR_perf_event_open, &attr, -1, 0, -1, PERF_FLAG_FD_CLOEXEC);
  if (fd < 0) {
    fprintf(
        stderr,
        "failed to create perf event for kprobe ID %d: %d\n",
        id,
        -errno);
    goto err_out;
  }

  link = bpf_program__attach_perf_event(prog, fd);
  err = libbpf_get_error(link);
  if (err) {
    fprintf(stderr, "failed to attach to perf event FD %d: %d\n", fd, err);
    goto err_out;
  }

  return link;

err_out:
  if (f)
    fclose(f);
  if (fd >= 0)
    close(fd);
  remove_kprobe_event(func_name, is_kretprobe);
  return NULL;
}


Then you'd use it in your application as:

...

  skel->links.handler = attach_kprobe_legacy(
      skel->progs.handler, "do_sys_open", false /* is_kretprobe */);
  if (!skel->links.handler) {
    fprintf(stderr, "Failed to attach kprobe using legacy debugfs API!\n");
    err = 1;
    goto out;
  }

  ... kprobe is attached here ...

out:
  /* first clean up step */
  bpf_link__destroy(skel->links.handler);
  /* this is second necessary clean up step */
  remove_kprobe_event("do_sys_open", false /* is_kretprobe */);


Let me know if that worked.

> libbpf: prog 'kprobe__do_sys_open': failed to create kprobe
> 'do_sys_open' perf event: No such file or directory
> libbpf: failed to auto-attach program 'kprobe__do_sys_open': -2
> failed to attach BPF programs: No such file or directory
>

[...]

  parent reply	other threads:[~2020-09-29  1:29 UTC|newest]

Thread overview: 13+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-09-25 23:56 Help using libbpf with kernel 4.14 Yaniv Agman
2020-09-28  5:50 ` Andrii Nakryiko
2020-09-28 20:08   ` Yaniv Agman
2020-09-28 20:24     ` Andrii Nakryiko
2020-09-28 20:39       ` Yaniv Agman
2020-09-29  0:00       ` Yaniv Agman
2020-09-29  0:07         ` Yonghong Song
2020-09-29  0:16           ` Yaniv Agman
2020-09-29  1:28         ` Andrii Nakryiko [this message]
2020-09-29  8:25           ` Yaniv Agman
2020-09-30 18:34             ` Andrii Nakryiko
2020-10-04 22:52               ` Yaniv Agman
2020-10-05  4:29                 ` Andrii Nakryiko

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to='CAEf4BzZ=w++q3VVG8Mox4KsRHfY4P4J7G0Pnse2erWS6=OX3UQ@mail.gmail.com' \
    --to=andrii.nakryiko@gmail.com \
    --cc=bpf@vger.kernel.org \
    --cc=yanivagman@gmail.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).