I recently came across a mail exchange where the following runtime linker error message was observed:
illegal mode: potential multiple path expansion requires RTLD_FIRST
The exchange, and a quick review of the documents, reveal that some explanation wouldn't go amiss.
The runtime linker, ld.so.1, provides a number of tokens that can be used within dynamic linking string definitions. These string definitions can provide filters, dependencies and runpath information, and are documented in the section "Establishing Dependencies with Dynamic String Tokens" of the Linker and Libraries Guide.
Presently, a dependency expressed within an object, points to a single file. For example:
% elfdump -b main | fgrep NEEDED  NEEDED 0x230 libc.so.1
Filtee definitions and runpaths however, are frequently defined as a lists of colon separated items. For example:
% elfdump -d foo.so | egrep "FILTER|RPATH"  FILTER 0xd8e libbar.so.1:libnuts.so.1  RPATH 0xbf3 /usr/ISVI/lib:/usr/ISVII/lib
The tokens $OSNAME, $OSREL, $PLATFORM and $ORIGIN all expand into a single string. For example:
% elfdump -d libc_psr.so.1 | fgrep AUXILIARY  AUXILIARY 0x56ea /platform/$PLATFORM/lib/libc_psr.so.1
can expand at runtime into:
This single string expansion means that these tokens can be used in filter, dependency and runpath definitions.
The tokens $HWCAP and $ISALIST however, typically expand into a list of elements. For example:
% elfdump -d bar.so | fgrep RPATH  RPATH 0x1ad /usr/ISV/$ISALIST
can expand at runtime into:
search path=/usr/ISV/$ISALIST (RPATH from file bar.so) trying path=/usr/ISV/sparcv9+vis2/libfoo.so.1 trying path=/usr/ISV/sparcv9+vis/libfoo.so.1 trying path=/usr/ISV/sparcv9/libfoo.so.1 trying path=/usr/ISV/sparcv8plus+vis2/libfoo.so.1 ....
This list is well suited for filter and runpath definitions, where lists are already expected. But what about dependency definitions? As our present implementation of dependency strings expects a single object, allowing a token that can expand into multiple objects was questioned. Basically, the infrastructure to assign multiple head objects to a handle isn't yet available, and we really don't know of anyone wanted this capability.
Because of these issues, we decided to restrict the use of $HWCAP and $ISALIST when used to define dependencies. If you use either of these tokens to establish dependencies, only the first object that is found from their expansion is used. Note that pathnames used for dependencies don't seem very common, but we've restricted their use for these tokens anyway.
Likewise, if you use these tokens in a dlopen(3c), only the first object found is applicable. But here we wanted the user to be explicit, and know what they are getting. Hence, was ask for the RTLD_FIRST flag, which happened to be lying around and seemed kind of appropriate. Without this flag you'll get the illegal mode error message. Of course, the RTLD_FIRST is now a little overloaded, it restricts symbol searches, and clarifies a dlopen() request that might expand to multiple objects. Oh well.
For dlopen(), we could have enforced the RTLD_FIRST flag internally, but felt that one day we might want to enable the opening of multiple objects from one dlopen(). Without the user explicitly defining todays requirement it would be hard to extend the capabilities at a future date. The observant members of the audience will of course point out that we didn't make a similar explicit requirement for NEEDED dependencies. Sigh.
The illegal mode error message is an attempt to make users aware of a token processing restriction, that may be lifted in future.