Sample Header Ad - 728x90

How to use linux perf in a conda environment

1 vote
0 answers
52 views
I'm trying to use linux perf program in a conda environment, but the perf program seems to ignore the conda environment. I installed the conda-forge::linux-perf package in my conda environment, but when I run it I get this error:
$ perf record ls
perf: error while loading shared libraries: libdebuginfod.so.1: cannot open shared object file: No such file or directory
The library is installed in my conda environment:
$ ls $CONDA_PREFIX/lib/*debuginfod*
/home/pcarter/anaconda3/envs/spec_density/lib/libdebuginfod-0.191.so  /home/pcarter/anaconda3/envs/spec_density/lib/libdebuginfod.so.1
/home/pcarter/anaconda3/envs/spec_density/lib/libdebuginfod.so
But perf is not looking in this directory for libraries. Using strace, I'm able to see where it is only looking in the base system directories, not the conda ones.
execve("/home/pcarter/anaconda3/envs/spec_density/bin/perf", ["perf", "record", "ls"], 0x7ffe078205b0 /* 99 vars */) = 0
access("/etc/suid-debug", F_OK)         = -1 ENOENT (No such file or directory)
brk(NULL)                               = 0x556c19e15000
fcntl(0, F_GETFD)                       = 0
fcntl(1, F_GETFD)                       = 0
fcntl(2, F_GETFD)                       = 0
access("/etc/suid-debug", F_OK)         = -1 ENOENT (No such file or directory)
readlink("/proc/self/exe", "/home/pcarter/anaconda3/envs/spe"..., 4096) = 50
access("/etc/ld.so.preload", R_OK)      = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=138259, ...}) = 0
mmap(NULL, 138259, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7f9bf8a59000
close(3)                                = 0
openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libpthread.so.0", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0 l\0\0\0\0\0\0"..., 832) = 832
...
openat(AT_FDCWD, "/lib/x86_64-linux-gnu/tls/haswell/x86_64/libdebuginfod.so.1", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
stat("/lib/x86_64-linux-gnu/tls/haswell/x86_64", 0x7fffe984d610) = -1 ENOENT (No such file or directory)
...
openat(AT_FDCWD, "/usr/lib/libdebuginfod.so.1", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
stat("/usr/lib", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0
This is not what happens for other conda installed programs. Looking at strace output for running the nasm program, it is looking at the conda lib directory.
execve("/home/pcarter/anaconda3/envs/spec_density/bin/nasm", ["nasm"], 0x7ffffc123b60 /* 99 vars */) = 0
brk(NULL)                               = 0x189a000
readlink("/proc/self/exe", "/home/pcarter/anaconda3/envs/spe"..., 4096) = 50
access("/etc/ld.so.preload", R_OK)      = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/home/pcarter/anaconda3/envs/spec_density/bin/../lib/tls/haswell/x86_64/libc.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
stat("/home/pcarter/anaconda3/envs/spec_density/bin/../lib/tls/haswell/x86_64", 0x7ffe9d0a04f0) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/home/pcarter/anaconda3/envs/spec_density/bin/../lib/tls/haswell/libc.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
stat("/home/pcarter/anaconda3/envs/spec_density/bin/../lib/tls/haswell", 0x7ffe9d0a04f0) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/home/pcarter/anaconda3/envs/spec_density/bin/../lib/tls/x86_64/libc.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
stat("/home/pcarter/anaconda3/envs/spec_density/bin/../lib/tls/x86_64", 0x7ffe9d0a04f0) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/home/pcarter/anaconda3/envs/spec_density/bin/../lib/tls/libc.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
stat("/home/pcarter/anaconda3/envs/spec_density/bin/../lib/tls", 0x7ffe9d0a04f0) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/home/pcarter/anaconda3/envs/spec_density/bin/../lib/haswell/x86_64/libc.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
stat("/home/pcarter/anaconda3/envs/spec_density/bin/../lib/haswell/x86_64", 0x7ffe9d0a04f0) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/home/pcarter/anaconda3/envs/spec_density/bin/../lib/haswell/libc.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
stat("/home/pcarter/anaconda3/envs/spec_density/bin/../lib/haswell", 0x7ffe9d0a04f0) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/home/pcarter/anaconda3/envs/spec_density/bin/../lib/x86_64/libc.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
stat("/home/pcarter/anaconda3/envs/spec_density/bin/../lib/x86_64", 0x7ffe9d0a04f0) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/home/pcarter/anaconda3/envs/spec_density/bin/../lib/libc.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
stat("/home/pcarter/anaconda3/envs/spec_density/bin/../lib", {st_mode=S_IFDIR|0755, st_size=20480, ...}) = 0
Is this a security feature of perf? If so, what do I need to do to fix this? FYI: I followed the instructions at this [page](https://www.kernel.org/doc/html/latest/admin-guide/perf-security.html) to enable my conda perf program to have the capabilities it needs.
$ sudo getcap /home/pcarter/anaconda3/envs/spec_density/bin/perf
/home/pcarter/anaconda3/envs/spec_density/bin/perf cap_sys_ptrace,cap_syslog,cap_perfmon=ep
**Update** I found a work around, but still don't completely understand what is going on. Using sudo to run perf as *root* fixes the issue.
$ sudo $CONDA_PREFIX/bin/perf record ls                                                      
# Output of ls redacted here                   
[ perf record: Woken up 1 times to write data ]                                                                                                                           
[ perf record: Captured and wrote 0.021 MB perf.data (7 samples) ]
(I have to specify the path to perf here since I'm using sudo which uses the *root* user's PATH) It looks like conda sets up the library search path using RPATH in the executable. If you use readelf to look at the perf binary, it returns:
$ readelf -d $CONDA_PREFIX/bin/perf

Dynamic section at offset 0x948bc0 contains 45 entries:
  Tag        Type                         Name/Value
 0x0000000000000001 (NEEDED)             Shared library: [libpthread.so.0]
 0x0000000000000001 (NEEDED)             Shared library: [librt.so.1]
 0x0000000000000001 (NEEDED)             Shared library: [libm.so.6]
 0x0000000000000001 (NEEDED)             Shared library: [libdl.so.2]
 0x0000000000000001 (NEEDED)             Shared library: [libelf.so.1]
 0x0000000000000001 (NEEDED)             Shared library: [libdebuginfod.so.1]
 0x0000000000000001 (NEEDED)             Shared library: [libdw.so.1]
 0x0000000000000001 (NEEDED)             Shared library: [libunwind-x86_64.so.8]
 0x0000000000000001 (NEEDED)             Shared library: [libunwind.so.8]
 0x0000000000000001 (NEEDED)             Shared library: [liblzma.so.5]
 0x0000000000000001 (NEEDED)             Shared library: [libcrypto.so.3]
 0x0000000000000001 (NEEDED)             Shared library: [libpython3.12.so.1.0]
 0x0000000000000001 (NEEDED)             Shared library: [libz.so.1]
 0x0000000000000001 (NEEDED)             Shared library: [libzstd.so.1]
 0x0000000000000001 (NEEDED)             Shared library: [libcap.so.2]
 0x0000000000000001 (NEEDED)             Shared library: [libnuma.so.1]
 0x0000000000000001 (NEEDED)             Shared library: [libc.so.6]
 0x000000000000000f (RPATH)              Library rpath: [$ORIGIN/../lib]
where $ORIGIN represents the directory the executable is in. So RPATH does point to the conda lib directory. However, perf seems to be setup to ignore this depending on properties of the user running it. It does use it for *root* but not for my user account. I assume this is for security reasons. Is there a way to enable this for my user account?
Asked by pcarter (111 rep)
Mar 3, 2025, 10:17 PM
Last activity: Mar 4, 2025, 11:37 PM