readelf reports so file as NEEDED, but no functions (or other symbols) is used from it - linux

Readelf reports, that libutil.so.1 is needed by ssh utility:
$readelf -s /usr/bin/ssh | grep libutil
0x0000000000000001 (NEEDED) Shared library: [libutil.so.1]
As nm says, libutil.so.1 has only 6 external symbols:
$nm -D /lib64/libutil.so.1 | grep "T "
000000331e0015a0 T forkpty
000000331e000fa0 T login
000000331e0010f0 T login_tty
000000331e001190 T logout
000000331e0012e0 T logwtmp
000000331e0013d0 T openpty
But these symbols not referenced from ssh:
$nm -D /usr/bin/ssh | grep forkpty
$nm -D /usr/bin/ssh | grep login
$nm -D /usr/bin/ssh | grep login_tty
$nm -D /usr/bin/ssh | grep logout
$nm -D /usr/bin/ssh | grep logwtmp
$nm -D /usr/bin/ssh | grep openpty
(grep not showing any matches)
What's going on? Why library referenced as NEEDED, but no symbols from it used? This is not sole example. I met many such "empty" references, while analysing dependencies of another executables.

The DT_NEEDED tagging is generated by the link editor (ld) based on the -l flags provided. The default for the GNU link editor and most other editors, with some exceptions, is to create a DT_NEEDED tag for each -l flag provided.
When using GNU ld or gold, you can pass --as-needed before the -l flags to only emit DT_NEEDED tags for the libraries that are indeed used. This may still emit not obvious tags if the symbols are actually used indirectly.
I have actually written a significant amount about --as-needed and how it works, so you can look through my blog posts if you are more curious.

Related

How to use xargs to get elapsed time for running processes

I want get the run times of some processes. Here is what I am doing
ps -ef | grep "python3 myTask.py" | awk '{print $2}' | xargs -n1 ps -p {} -o etime
I want to get the pids by
ps -ef | grep "python3 myTask.py" | awk '{print $2}'
then pass these along to the
ps -p {} -o etime
by using xargs, but its not working. I get
error: process ID list syntax error
Usage:
ps [options]
Try 'ps --help <simple|list|output|threads|misc|all>'
or 'ps --help <s|l|o|t|m|a>'
for additional help text.
For more details see ps(1).
error: process ID list syntax error
Usage:
ps [options]
Try 'ps --help <simple|list|output|threads|misc|all>'
or 'ps --help <s|l|o|t|m|a>'
for additional help text.
For more details see ps(1).
what am i doing wrong?
You can use the following command:
pgrep -f "python3 myTask.py" | xargs -i{} ps -p {} -o etime
pgrep - Look up or signal processes based on name and other attributes.
-f, --full -
The pattern is normally only matched against the process name. When -f is set, the full command line is
used.
For further reading, see man pgrep.
The missing part from the xargs segment was -i{}, which invokes the command for each argument, whilst {} will be replaced by it.
-i[replace-str], --replace[=replace-str] -
This option is a synonym for -Ireplace-str if replace-str is specified.
For further reading, see man xargs.
You must provide -I{} to xargs to set the placeholder; otherwise it cannot be used.
Nevertheless, your command is too complicated and involves too many intermediate steps (and a race-condition). Simply get your processes including elapsed time and filter the lines you need:
ps -eo etime,cmd | awk '/python3 myTask.py/{print $1}'
(no xargs anymore)

Unable to redirect error to /dev/null in gnu make

In a gnu script, I want to check if an intel c compiler is in the path.
To do this, I run the following command:
COMPILER_IN_PATH := $(shell icc -dumpversion | grep 2021.3.0)
Later I test to see if COMPILER_IN_PATH is set.
If an intel compiler is in the path, the above command works fine.
However, if an intel compiler is not in the path, though the above command works (COMPILER_IN_PATH will not be set), I see the following error message in the output when this line is run:
/bin/sh: icc: command not found
I would like to get rid of that error message. How do I redirect stderr somewhere (to /dev/null, I suppose) while reading the stdout into the COMPILER_IN_PATH variable ?
Here are some of my failed attempts:
icc -dumpversion | grep 2021 > /dev/null 2>&1
Ambiguous output redirect.
icc -dumpversion | grep 2021 2> /dev/null
icc: Command not found.
grep: 2: No such file or directory
You are redirecting the output of the grep command. You want to redirect the output of the icc command.
COMPILER_IN_PATH := $(shell icc -dumpversion 2>/dev/null | grep 2021.3.0)

Where does g++ look for libraries to link?

So I'm currently using Lubuntu 18.4 32bit and was trying to get the GLFW library up and going. I noticed that when you compile a program using GLFW you need to link many libraries and was wondering where exactly does g++ look in the filesystem when you type g++ main.cpp -lglfw?
For compiler:
echo | g++ -x c++ -E -Wp,-v - >/dev/null
echo | prints empty "source code" and closes stdin
-x c++ to specify the language (with this option it prints more detailed info)
-E says g++ to stop after preprocessing stage
- at the end means read code from stdin
-Wp,-v to pass -v directly to preprocessor
>/dev/null to redirect extra output to /dev/null (void)
Example output:
ignoring nonexistent directory "/usr/lib/gcc/x86_64-pc-linux-gnu/10.2.0/../../../../x86_64-pc-linux-gnu/include"
#include "..." search starts here:
#include <...> search starts here:
/usr/lib/gcc/x86_64-pc-linux-gnu/10.2.0/../../../../include/c++/10.2.0
/usr/lib/gcc/x86_64-pc-linux-gnu/10.2.0/../../../../include/c++/10.2.0/x86_64-pc-linux-gnu
/usr/lib/gcc/x86_64-pc-linux-gnu/10.2.0/../../../../include/c++/10.2.0/backward
/usr/lib/gcc/x86_64-pc-linux-gnu/10.2.0/include
/usr/local/include
/usr/lib/gcc/x86_64-pc-linux-gnu/10.2.0/include-fixed
/usr/include
End of search list.
For linker:
ld --verbose | grep SEARCH_DIR | tr -s ' ;' \\012
--verbose tells ld to print settings info
| grep SEARCH_DIR select lib directory info
| tr -s ' ;' \\012 makes output pretty (replace ; with new line)
Example output:
SEARCH_DIR("/usr/x86_64-pc-linux-gnu/lib64")
SEARCH_DIR("/usr/lib")
SEARCH_DIR("/usr/local/lib")
SEARCH_DIR("/usr/x86_64-pc-linux-gnu/lib")
So the GLFW library should be in one of those directories.
Source: https://transang.me/library-path-in-gcc/

How to find all shared libraries actually used during execution in Linux?

I have an executable and I would like to find out which shared libraries were actually used during a specific run. I know ldd would list all the shared library dependencies of that executable but I would like to find out the subset of those that were actually used during a specific run*. Is this possible?
*what I mean with specific run is running the executable with certain input parameters that would cause only a small part of the code to be run.
You can use ltrace(1) for this:
$ PROG='ls -l'
# Collect call info
$ ltrace -o calls.txt -l '*' $PROG &> /dev/null
# Analyze collected data
$ cat calls.txt | sed -ne '/->/{ s/^\(.*\)->.*/\1/; p }' | sort -u
libacl.so.1
libcap.so.2
libc.so.6
libselinux.so.1
ls
# Compare with ldd
$ ldd /bin/ls | wc -l
10
You could use strace and grep for open .so files.
strace $MYPROG | grep -E '^open*\.so
lsof also should work to grep for open libraries.
lsof -p $PID | awk '{print $9}' | grep '\.so'
This assumes the shared libraries have .so extension

Yocto: bitbake command to regenerate all RPM files

I wanted to make some free space and deleted all directories in build/tmp/deploy/rpm/, thinking yocto would detect it and recreate them at the next bitbake call... it was a mistake ! :(
Here's the bitbake error just in case:
bitbake <image_name>
[...]
ERROR: ... do_rootfs: minicom not found in the base feeds (<image_name> corei7-64-intel-common corei7-64 core2-64 x86_64 noarch any all).
[...list of every package...]
Is there any way to force the regeneration of every rpms using bitbake ?
Forcing the regeneration with bitbake -f -c package_write_rpm <package> works, but I didn't find the command to do it all at once.
I tried cleaning the state of the native rpm packages thinking it might detect it and invalidate the rpm files states, but no luck:
bitbake -f -c cleanall nativesdk-rpm nativesdk-rpmresolve rpmresolve-native rpm-native
bitbake <image_name>
I also thought this would work, but it didn't:
bitbake -f -c package_write_rpm <image_name>
I will try to hack something with bitbake-layers show-recipes and xargs, but it would be cool to have a proper bitbake command.
I am using Yocto 2.1 (Krogoth).
Thanks !
I ended up doing the following script and use bitbake dependency tree to get the list of packages (thanks to this yocto/bitbake reference page):
# bitbake -g <image> && cat pn-depends.dot | grep -v -e '-native' | grep -v digraph | grep -v -e '-image' | awk '{print $1}' | sort | uniq | grep -v "}" | grep -v cross | grep -v gcc | grep -v glibc > packages-list.txt
# cat packages-list.txt | xargs bitbake -f -c package_write_rpm
Maybe there is a more straightforward solution ? For now this worked.

Resources