From: Namhyung Kim <namhyung@kernel.org>
To: Ze Xia <xiaze2017@stu.xjtu.edu.cn>
Cc: Peter Zijlstra <peterz@infradead.org>,
Ingo Molnar <mingo@red-hat.com>,
Arnaldo Carvalho de Melo <acme@kernel.org>,
linux-perf-users@vger.kernel.org
Subject: Re: Bug with 'perf script --symfs'?
Date: Fri, 12 Jul 2024 15:13:57 -0500 [thread overview]
Message-ID: <ZpGOhXCAdz8ks6Y2@google.com> (raw)
In-Reply-To: <1a8b2c39.69b.1909152714b.Coremail.xiaze2017@stu.xjtu.edu.cn>
Hello,
On Mon, Jul 08, 2024 at 03:50:17PM +0800, Ze Xia wrote:
> Hi,
>
> I think I found that `perf script --symfs` option and automatic namespace attaching seems to conflict.
>
> Environment: kernel version `6.5.0-41-generic`, distribution `ubuntu22.04`, arch `x86_64`
>
> Behavior: In `perf script`, if a process is inside another namespace than the default (e.g. inside a docker container), perf script will try to attach to that namespace to read debug info. However, if `--symfs` option is provided, then it will search for debug files with `symfs` prefix *inside the namespace*. Usually the symfs directory isn't present in the namespace, thus I see this behavior as inappropriate.
>
> To reproduce: I run commands below on a ubuntu machine with docker installed. Any glibc based distro without musl installed should also reproduce the issue, as musl isn't present at host but present in the docker container.
>
> In one terminal (create the process to be profiled):
>
> $ docker run -it --rm --name test-symfs --net=host alpine
> # now we're inside the container
> $ apk add musl-dbg
> $ dd if=/dev/zero of=/dev/null
> # it stucks here, don't kill it yet
>
> In another terminal (profiling):
>
> $ perf record -a -g sleep 1
> $ perf script > success.perf
> $ grep musl success.perf | head -n 10
> 75fbf5143992 __cp_end+0x0 (/lib/ld-musl-x86_64.so.1)
> 75fbf5143992 __cp_end+0x0 (/lib/ld-musl-x86_64.so.1)
> 75fbf5143992 __cp_end+0x0 (/lib/ld-musl-x86_64.so.1)
> 75fbf5143992 __cp_end+0x0 (/lib/ld-musl-x86_64.so.1)
> 75fbf5143992 __cp_end+0x0 (/lib/ld-musl-x86_64.so.1)
> 75fbf5143992 __cp_end+0x0 (/lib/ld-musl-x86_64.so.1)
> 75fbf5143992 __cp_end+0x0 (/lib/ld-musl-x86_64.so.1)
> 75fbf5143992 __cp_end+0x0 (/lib/ld-musl-x86_64.so.1)
> 75fbf5143992 __cp_end+0x0 (/lib/ld-musl-x86_64.so.1)
> 75fbf5143992 __cp_end+0x0 (/lib/ld-musl-x86_64.so.1)
>
> Thanks to automatic namespace attaching, this works. Problem comes with `--symfs` option:
>
> $ docker cp test-symfs:/ ./symfs
> $ perf script --symfs ./symfs > fail.perf
> $ grep musl fail.perf | head -n 10
> 75fbf5143992 [unknown] (/lib/ld-musl-x86_64.so.1)
> 75fbf5143992 [unknown] (/lib/ld-musl-x86_64.so.1)
> 75fbf5143992 [unknown] (/lib/ld-musl-x86_64.so.1)
> 75fbf5143992 [unknown] (/lib/ld-musl-x86_64.so.1)
> 75fbf5143992 [unknown] (/lib/ld-musl-x86_64.so.1)
> 75fbf5143992 [unknown] (/lib/ld-musl-x86_64.so.1)
> 75fbf5143992 [unknown] (/lib/ld-musl-x86_64.so.1)
> 75fbf5143992 [unknown] (/lib/ld-musl-x86_64.so.1)
> 75fbf5143992 [unknown] (/lib/ld-musl-x86_64.so.1)
> 75fbf5143992 [unknown] (/lib/ld-musl-x86_64.so.1)
>
> We can't find the symbol any more.
>
> Rerun the `perf script` with `strace`:
>
> $ strace -o fail.strace perf script --symfs ./symfs > fail.perf
> $ grep musl fail.strace | grep stat
> newfstatat(AT_FDCWD, "./symfs//lib/ld-musl-x86_64.so.1", 0x7ffce53b7030, 0) = -1 ENOENT (No such file or directory)
> newfstatat(AT_FDCWD, "./symfs//lib/ld-musl-x86_64.so.1", 0x7ffce53b2140, 0) = -1 ENOENT (No such file or directory)
> newfstatat(AT_FDCWD, "./symfs//usr/lib/debug/lib/ld-musl-x86_64.so.1.debug", 0x7ffce53b41a0, 0) = -1 ENOENT (No such file or directory)
> newfstatat(AT_FDCWD, "./symfs//usr/lib/debug/lib/ld-musl-x86_64.so.1", 0x7ffce53b41a0, 0) = -1 ENOENT (No such file or directory)
> newfstatat(AT_FDCWD, "./symfs//lib/ld-musl-x86_64.so.1", 0x7ffce53b41a0, 0) = -1 ENOENT (No such file or directory)
> newfstatat(AT_FDCWD, "./symfs//lib/.debug/ld-musl-x86_64.so.1", 0x7ffce53b41a0, 0) = -1 ENOENT (No such file or directory)
>
> Note how `./symfs/` is included in all those calls.
>
> Rerun the success case with strace:
>
> $ strace -o success.strace perf script > success.perf
> $ grep musl success.strace | grep stat
> newfstatat(AT_FDCWD, "/lib/ld-musl-x86_64.so.1", {st_mode=S_IFREG|0755, st_size=649832, ...}, 0) = 0
> newfstatat(AT_FDCWD, "ld-musl-x86_64.so.1.debug", 0x7ffe0949a350, 0) = -1 ENOENT (No such file or directory)
> newfstatat(AT_FDCWD, "/lib/ld-musl-x86_64.so.1.debug", 0x7ffe0949a350, 0) = -1 ENOENT (No such file or directory)
> newfstatat(AT_FDCWD, "/lib/.debug/ld-musl-x86_64.so.1.debug", 0x7ffe0949a350, 0) = -1 ENOENT (No such file or directory)
> newfstatat(AT_FDCWD, "/usr/lib/debug/lib/ld-musl-x86_64.so.1.debug", {st_mode=S_IFREG|0755, st_size=2892848, ...}, 0) = 0
> newfstatat(AT_FDCWD, "/usr/lib/debug/lib/ld-musl-x86_64.so.1.debug", {st_mode=S_IFREG|0755, st_size=2892848, ...}, 0) = 0
>
> Note that the calls without `./symfs/` worked, because perf is inside the container's namespace.
>
> To prove that our symfs indeed contains the debug info, we can stop the `dd` command inside docker and rerun `perf script` without `--symfs` option, it also succeeds:
>
> $ strace -o success2.strace perf script --symfs ./symfs > success2.perf
> $ grep musl success2.perf | head -n 10
> 75fbf5143992 __cp_end+0x0 (/lib/ld-musl-x86_64.so.1)
> 75fbf5143992 __cp_end+0x0 (/lib/ld-musl-x86_64.so.1)
> 75fbf5143992 __cp_end+0x0 (/lib/ld-musl-x86_64.so.1)
> 75fbf5143992 __cp_end+0x0 (/lib/ld-musl-x86_64.so.1)
> 75fbf5143992 __cp_end+0x0 (/lib/ld-musl-x86_64.so.1)
> 75fbf5143992 __cp_end+0x0 (/lib/ld-musl-x86_64.so.1)
> 75fbf5143992 __cp_end+0x0 (/lib/ld-musl-x86_64.so.1)
> 75fbf5143992 __cp_end+0x0 (/lib/ld-musl-x86_64.so.1)
> 75fbf5143992 __cp_end+0x0 (/lib/ld-musl-x86_64.so.1)
> 75fbf5143992 __cp_end+0x0 (/lib/ld-musl-x86_64.so.1)
> $ grep musl success2.strace | grep stat
> newfstatat(AT_FDCWD, "./symfs//lib/ld-musl-x86_64.so.1", 0x7ffe14d3d6a0, 0) = -1 ENOENT (No such file or directory)
> newfstatat(AT_FDCWD, "./symfs//lib/ld-musl-x86_64.so.1", {st_mode=S_IFREG|0755, st_size=649832, ...}, 0) = 0
> newfstatat(AT_FDCWD, "ld-musl-x86_64.so.1.debug", 0x7ffe14d387a0, 0) = -1 ENOENT (No such file or directory)
> newfstatat(AT_FDCWD, "./symfs//lib/ld-musl-x86_64.so.1.debug", 0x7ffe14d387a0, 0) = -1 ENOENT (No such file or directory)
> newfstatat(AT_FDCWD, "./symfs//lib/.debug/ld-musl-x86_64.so.1.debug", 0x7ffe14d387a0, 0) = -1 ENOENT (No such file or directory)
> newfstatat(AT_FDCWD, "/usr/lib/debug./symfs//lib/ld-musl-x86_64.so.1.debug", 0x7ffe14d387a0, 0) = -1 ENOENT (No such file or directory)
> newfstatat(AT_FDCWD, "./symfs//usr/lib/debug/lib/ld-musl-x86_64.so.1.debug", {st_mode=S_IFREG|0755, st_size=2892848, ...}, 0) = 0
> newfstatat(AT_FDCWD, "./symfs//usr/lib/debug/lib/ld-musl-x86_64.so.1", 0x7ffe14d3a810, 0) = -1 ENOENT (No such file or directory)
> newfstatat(AT_FDCWD, "./symfs//lib/ld-musl-x86_64.so.1", {st_mode=S_IFREG|0755, st_size=649832, ...}, 0) = 0
>
> As the `dd` process is dead now, `perf script` will not attach to its namespace. It reads debug info from our symfs, and it worked.
>
> Expected Behavior: `symfs` is prefixed only if no namespace attaching happened. Or, to be conversative, try twice, with or without `--symfs`.
I'm not sure if it's the reasonable expectation. With --symfs, you can
expect it will prefix the path to all DSO paths. The namespace makes
things complicated but I think the symfs behaivor is simple. There's no
guarantee if the symfs is always out of the namespace, right?
Thanks,
Namhyung
prev parent reply other threads:[~2024-07-12 20:14 UTC|newest]
Thread overview: 2+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-07-08 7:50 Bug with 'perf script --symfs'? Ze Xia
2024-07-12 20:13 ` Namhyung Kim [this message]
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=ZpGOhXCAdz8ks6Y2@google.com \
--to=namhyung@kernel.org \
--cc=acme@kernel.org \
--cc=linux-perf-users@vger.kernel.org \
--cc=mingo@red-hat.com \
--cc=peterz@infradead.org \
--cc=xiaze2017@stu.xjtu.edu.cn \
/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).