This addresses issue #3862 (originally #460 (closed)) by implementing code that parses the search paths in /etc/ld.so.conf for the private loader on Linux.
The /etc/ld.so.conf file consists of one or more lines, where a line may be a search path, an include directive to include another configuration file or where a line may start with '#' if it is a comment. The include directives support globbing (see man 3 glob and man 7 glob for more information).
Some notes about compatibility:
- Alpine is a musl-based distribution, and the dynamic linker used by Alpine instead may look for
/etc/ld-musl-$(ARCH).path. For instance, on x86-64, it would look for/etc/ld-musl-x86_64.path. The format seems to be slightly different from/etc/ld.so.conf. If the file is not present, musl simply defaults to "/lib:/usr/local/lib:/usr/lib". See also: https://www.musl-libc.org/doc/1.0.0/manual.html - Android uses bionic as its libc and instead looks for
/system/etc/ld.config.txt. See also: https://android.googlesource.com/platform/bionic/+/master/linker/ld.config.format.md - While the FreeBSD man pages do seem to mention the existence of
/etc/ld.so.conf, the default seems to be that the dynamic linker on FreeBSD looks for theldconfig_pathsandldconfig32_pathskeys in/etc/defaults/rc.conf. - Mac OS X does not seem to have
/etc/ld.so.confeither, butman dyldseems to provide some useful hints.
We probably want to open new issues referring to #3862 and #460 (closed) for the other cases.
This PR implements the following:
- The
strncasecmpfunction to match theincludedirective. On second thought,strncmpmay work well enough, but it doesn't hurt to be case-insensitive. - The
fnmatchfunction, which is required to implementglob. Thefnmatchlets us match a given string against a pattern including character ranges (e.g.[a-z]), the any character (denoted as?) and wildcards (denoted as '*'). Furthermore, multiple wildcards may be present. - The
globfunction which usesfnmatchfunction and the Unix-specific directory iterator code that is currently present in DynamoRIO to match all found filenames against a given pattern. - The
getdelimandgetlinefunctions which help us parse the config files line-by-line. - The
privload_parse_ld_conffunction which parses/etc/ld.so.confand any included config files and constructs an array of search paths by piggybacking on theglobfunction, which can be used to append search paths to an array of search paths. - Finally, the
privload_locatefunction has been extended to use theprivload_parse_ld_conf, and otherwise falls back to the fixed array of system paths (see compatibility notes).
While the ld.so.conf parsing itself is straight-forward on any POSIX system due to the existence of glob and getline, DynamoRIO originally did not provide these functions as the private loader cannot rely on libc, and it would be helpful to have a thorough review of the implementation of these functions.
I have tested this on:
- My desktop running Gentoo where
libgcc_s.so.1is located in/usr/lib/gcc/x86_64-pc-linux-gnu/11.2.0by running:./bin64/drrun -c ./api/bin/libempty.so -- ls. Before these changes, it was necessary to specify the correct path using theLD_LIBRARY_PATHenvironment variable. - Ubuntu 20.04 LTS by running:
./bin64/drrun -c /api/bin/libempty.so -- lsto be sure that there are no regressions introduced by this PR.